am ced71a50: am 99a25a47: am 5321ebb7: am 6d949cbf: am 951aa4f4: am 531968cf: am cb11b9ff: Tests for API to check certificate chain signatures
* commit 'ced71a503c6cf79b0cee407123d9df94bf988e0b':
Tests for API to check certificate chain signatures
diff --git a/Android.mk b/Android.mk
index a0599cf..2e9b76e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -61,9 +61,12 @@
dalvik \
$(HOST_OUT)/bin/dalvikvm \
$(HOST_OUT)/bin/dexopt \
+ $(HOST_OUT)/lib/libconscrypt_jni.so \
$(HOST_OUT)/lib/libjavacore.so \
cacerts-host \
core-hostdex \
+ conscrypt-hostdex \
+ okhttp-hostdex \
bouncycastle-hostdex \
apache-xml-hostdex \
apache-harmony-tests-hostdex \
diff --git a/Docs.mk b/Docs.mk
index 875a008..48cfd03 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -21,6 +21,8 @@
dalvik/src/main/java/dalvik/annotation \
dalvik/src/main/java/dalvik/bytecode \
json/src/main/java \
+ libdvm/src/main/java/dalvik \
+ libdvm/src/main/java/java \
luni/src/main/java/java \
luni/src/main/java/javax \
luni/src/main/java/org/xml/sax \
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 98de1f2..673c0bf 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -50,7 +50,8 @@
endef
# The Java files and their associated resources.
-core_src_files := $(call all-main-java-files-under,dalvik dom json luni support xml)
+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)
core_resource_dirs := $(call all-core-resource-dirs,main)
test_resource_dirs := $(call all-core-resource-dirs,test)
@@ -90,15 +91,40 @@
core-intermediates := ${intermediates}
-# Make the core-tests library.
-ifeq ($(LIBCORE_SKIP_TESTS),)
+# Create the conscrypt library
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
+LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+LOCAL_JAVA_LIBRARIES := core
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := conscrypt
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_JAVA_LIBRARY)
+
+# Create the conscrypt library without jarjar for tests
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+LOCAL_JAVA_LIBRARIES := core
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVACFLAGS := $(local_javac_flags)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := conscrypt-nojarjar
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+include $(BUILD_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_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
-LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc mockwebserver nist-pkix-tests
+LOCAL_JAVA_LIBRARIES := bouncycastle core conscrypt-nojarjar core-junit okhttp
+LOCAL_STATIC_JAVA_LIBRARIES := 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)
@@ -123,6 +149,12 @@
# Build for the host.
#
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := $(call all-main-java-files-under, dex)
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE := dex-host
+include $(BUILD_HOST_JAVA_LIBRARY)
+
ifeq ($(WITH_HOST_DALVIK),true)
# Definitions to make the core library.
@@ -145,15 +177,41 @@
include $(BUILD_HOST_JAVA_LIBRARY)
+ # Make the conscrypt-hostdex library
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+ LOCAL_JAVA_LIBRARIES := core-hostdex
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVACFLAGS := $(local_javac_flags)
+ LOCAL_JARJAR_RULES := $(LOCAL_PATH)/crypto/jarjar-rules.txt
+ LOCAL_BUILD_HOST_DEX := true
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := conscrypt-hostdex
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+ include $(BUILD_HOST_JAVA_LIBRARY)
+
+ # Make the conscrypt-hostdex-nojarjar for tests
+ include $(CLEAR_VARS)
+ LOCAL_SRC_FILES := $(call all-main-java-files-under,crypto)
+ LOCAL_JAVA_LIBRARIES := core-hostdex
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVACFLAGS := $(local_javac_flags)
+ LOCAL_BUILD_HOST_DEX := true
+ LOCAL_MODULE_TAGS := optional
+ LOCAL_MODULE := conscrypt-hostdex-nojarjar
+ LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
+ include $(BUILD_HOST_JAVA_LIBRARY)
+
# Make the core-tests library.
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
- LOCAL_SRC_FILES := $(call all-test-java-files-under,dalvik dom json luni support xml)
+ LOCAL_SRC_FILES := $(call all-test-java-files-under,crypto dalvik dom json luni support xml)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
- LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex core-junit-hostdex
+ LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-hostdex conscrypt-hostdex-nojarjar core-junit-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
diff --git a/NativeCode.mk b/NativeCode.mk
index b7c8b0e..3a22575 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -52,29 +52,6 @@
# sub.mk files don't see anything stray from the last rule that was
# set up.
-# Set up the test library first
-ifeq ($(LIBCORE_SKIP_TESTS),)
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(core_magic_local_target)
-core_src_files :=
-
-# Include the sub.mk files.
-$(foreach dir, \
- luni/src/test/native, \
- $(eval $(call include-core-native-dir,$(dir))))
-
-# This is for the test library, so rename the variable.
-test_src_files := $(core_src_files)
-core_src_files :=
-
-# Extract out the allowed LOCAL_* variables. Note: $(sort) also
-# removes duplicates.
-test_c_includes := $(sort libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
-test_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
-test_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
-endif # LIBCORE_SKIP_TESTS
-
-
include $(CLEAR_VARS)
LOCAL_MODULE := $(core_magic_local_target)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
@@ -82,67 +59,52 @@
# Include the sub.mk files.
$(foreach dir, \
- dalvik/src/main/native luni/src/main/native, \
+ crypto/src/main/native dalvik/src/main/native luni/src/main/native, \
$(eval $(call include-core-native-dir,$(dir))))
-# Extract out the allowed LOCAL_* variables. Note: $(sort) also
-# removes duplicates.
-core_c_includes := $(sort libcore/include $(LOCAL_C_INCLUDES) $(JNI_H_INCLUDE))
-core_shared_libraries := $(sort $(LOCAL_SHARED_LIBRARIES))
-core_static_libraries := $(sort $(LOCAL_STATIC_LIBRARIES))
+# Extract out the allowed LOCAL_* variables.
+core_c_includes := libcore/include $(LOCAL_C_INCLUDES)
+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_test_files := \
+ luni/src/test/native/test_openssl_engine.cpp \
#
# Build for the target (device).
#
include $(CLEAR_VARS)
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
LOCAL_CFLAGS += $(core_cflags)
LOCAL_CPPFLAGS += $(core_cppflags)
-ifeq ($(TARGET_ARCH),arm)
-# Ignore "note: the mangling of 'va_list' has changed in GCC 4.4"
-LOCAL_CFLAGS += -Wno-psabi
-endif
-
-# Define the rules.
-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_STATIC_LIBRARIES := $(core_static_libraries)
+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_STATIC_LIBRARIES += $(core_static_libraries)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacore
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-
-LOCAL_C_INCLUDES += external/stlport/stlport bionic/ bionic/libstdc++/include
-LOCAL_SHARED_LIBRARIES += libstlport
-
+include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
-# Test library
+# Test JNI library.
ifeq ($(LIBCORE_SKIP_TESTS),)
-include $(CLEAR_VARS)
-LOCAL_CFLAGS += -Wall -Wextra -Werror
+include $(CLEAR_VARS)
LOCAL_CFLAGS += $(core_cflags)
LOCAL_CPPFLAGS += $(core_cppflags)
-ifeq ($(TARGET_ARCH),arm)
-# Ignore "note: the mangling of 'va_list' has changed in GCC 4.4"
-LOCAL_CFLAGS += -Wno-psabi
-endif
-
-# Define the rules.
-LOCAL_SRC_FILES := $(test_src_files)
-LOCAL_C_INCLUDES := $(test_c_includes)
-LOCAL_SHARED_LIBRARIES := $(test_shared_libraries)
-LOCAL_STATIC_LIBRARIES := $(test_static_libraries)
+LOCAL_SRC_FILES += $(core_test_files)
+LOCAL_C_INCLUDES += libcore/include external/openssl/include
+LOCAL_SHARED_LIBRARIES += libcrypto
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacoretests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
-
+include external/stlport/libstlport.mk
include $(BUILD_SHARED_LIBRARY)
+
endif # LIBCORE_SKIP_TESTS
@@ -152,32 +114,44 @@
ifeq ($(WITH_HOST_DALVIK),true)
include $(CLEAR_VARS)
- # Define the rules.
- LOCAL_SRC_FILES := $(core_src_files)
+ LOCAL_SRC_FILES += $(core_src_files)
LOCAL_CFLAGS += $(core_cflags)
- LOCAL_C_INCLUDES := $(core_c_includes)
+ LOCAL_C_INCLUDES += $(core_c_includes)
LOCAL_CPPFLAGS += $(core_cppflags)
- LOCAL_LDLIBS += -ldl -lpthread
+ LOCAL_LDLIBS += -ldl -lpthread -lrt
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacore
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
- LOCAL_SHARED_LIBRARIES := $(core_shared_libraries) libexpat libicuuc libicui18n libssl libcrypto libz-host
- LOCAL_STATIC_LIBRARIES := $(core_static_libraries)
+ LOCAL_SHARED_LIBRARIES += $(core_shared_libraries) libexpat-host libicuuc-host libicui18n-host libssl-host libcrypto-host libz-host
+ 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)
+ 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_STATIC_LIBRARIES += $(core_static_libraries)
include $(BUILD_HOST_SHARED_LIBRARY)
ifeq ($(LIBCORE_SKIP_TESTS),)
include $(CLEAR_VARS)
- # Define the rules.
- LOCAL_SRC_FILES := $(test_src_files)
+ LOCAL_SRC_FILES += $(core_test_files)
LOCAL_CFLAGS += $(core_cflags)
- LOCAL_C_INCLUDES := $(test_c_includes)
+ LOCAL_C_INCLUDES += libcore/include external/openssl/include
LOCAL_CPPFLAGS += $(core_cppflags)
LOCAL_LDLIBS += -ldl -lpthread
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libjavacoretests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
- LOCAL_SHARED_LIBRARIES := $(test_shared_libraries)
- LOCAL_STATIC_LIBRARIES := $(test_static_libraries)
+ LOCAL_SHARED_LIBRARIES := libcrypto-host
include $(BUILD_HOST_SHARED_LIBRARY)
endif # LIBCORE_SKIP_TESTS
endif
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index ea4e91b..6902006 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -13,6 +13,7 @@
LOCAL_JAVA_LIBRARIES := \
bouncycastle \
+ conscrypt \
core
LOCAL_MODULE_TAGS := tests
diff --git a/benchmarks/src/benchmarks/regression/SignatureBenchmark.java b/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
index 383dcfd..373b876 100644
--- a/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/SignatureBenchmark.java
@@ -16,6 +16,7 @@
package benchmarks.regression;
+import com.android.org.conscrypt.OpenSSLSignature;
import com.google.caliper.Param;
import com.google.caliper.SimpleBenchmark;
import java.security.KeyPair;
@@ -25,7 +26,6 @@
import java.security.Signature;
import java.util.HashMap;
import java.util.Map;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature;
/**
* Tests RSA and DSA signature creation and verification.
diff --git a/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java b/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
index 36c5666..a4817b5 100644
--- a/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/URLConnectionBenchmark.java
@@ -18,8 +18,10 @@
import com.google.caliper.Param;
import com.google.caliper.SimpleBenchmark;
+import com.google.mockwebserver.Dispatcher;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
+import com.google.mockwebserver.RecordedRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
@@ -38,6 +40,16 @@
private MockWebServer server;
private URL url;
+ private static class SingleResponseDispatcher extends Dispatcher {
+ private MockResponse response;
+ SingleResponseDispatcher(MockResponse response) {
+ this.response = response;
+ }
+ @Override public MockResponse dispatch(RecordedRequest request) {
+ return response;
+ }
+ };
+
protected void setUp() throws Exception {
readBuffer = new byte[readBufferSize];
server = new MockWebServer();
@@ -45,10 +57,9 @@
MockResponse response = new MockResponse();
responseHeaders.apply(response);
transferEncoding.setBody(response, bodySize, chunkSize);
- server.enqueue(response);
// keep serving the same response for all iterations
- server.setSingleResponse(true);
+ server.setDispatcher(new SingleResponseDispatcher(response));
server.play();
url = server.getUrl("/");
@@ -56,14 +67,6 @@
}
protected void tearDown() throws Exception {
- /*
- * Entice the server to shut itself down gracefully. The shutdown method
- * doesn't work on Dalvik because socket.close() doesn't release blocked
- * threads. Instead, read the last continuously-served request, and then
- * cause the server to close the otherwise-reusable HTTP connection.
- */
- server.setSingleResponse(false);
- get();
server.shutdown();
}
diff --git a/crypto/jarjar-rules.txt b/crypto/jarjar-rules.txt
new file mode 100644
index 0000000..0eb6ac2
--- /dev/null
+++ b/crypto/jarjar-rules.txt
@@ -0,0 +1 @@
+rule org.conscrypt.** com.android.@0
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java b/crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
rename to crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
index 0d9b4fb..4aed70c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AbstractSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/AbstractSessionContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -23,6 +23,7 @@
import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Iterator;
@@ -31,7 +32,6 @@
import java.util.NoSuchElementException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSessionContext;
-import org.apache.harmony.security.provider.cert.X509CertImpl;
/**
* Supports SSL session caches.
@@ -82,7 +82,7 @@
}
}
- public final Enumeration getIds() {
+ public final Enumeration<byte[]> getIds() {
final Iterator<SSLSession> i = sessionIterator();
return new Enumeration<byte[]>() {
private SSLSession next;
@@ -243,12 +243,12 @@
dais.readFully(sessionData);
int count = dais.readInt();
- X509CertImpl[] certs = new X509CertImpl[count];
+ X509Certificate[] certs = new X509Certificate[count];
for (int i = 0; i < count; i++) {
length = dais.readInt();
byte[] certData = new byte[length];
dais.readFully(certData);
- certs[i] = new X509CertImpl(certData);
+ certs[i] = OpenSSLX509Certificate.fromX509Der(certData);
}
return new OpenSSLSessionImpl(sessionData, host, port, certs, this);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java b/crypto/src/main/java/org/conscrypt/AlertException.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
rename to crypto/src/main/java/org/conscrypt/AlertException.java
index fdc1cd9..a483021 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertException.java
+++ b/crypto/src/main/java/org/conscrypt/AlertException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.net.ssl.SSLException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java b/crypto/src/main/java/org/conscrypt/AlertProtocol.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
rename to crypto/src/main/java/org/conscrypt/AlertProtocol.java
index 2097bb0..0330e79 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/AlertProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/AlertProtocol.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* This class encapsulates the functionality of Alert Protocol.
@@ -155,9 +155,8 @@
* of the income TSL record: if it contains alert message from another
* peer, or if warning alert occured during the processing of the
* message and this warning should be sent to another peer.
- * @param level: alert level code
- * @param description: alert description code
- * @return
+ * @param level alert level code
+ * @param description alert description code
*/
protected void alert(byte level, byte description) {
if (logger != null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java b/crypto/src/main/java/org/conscrypt/Appendable.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
rename to crypto/src/main/java/org/conscrypt/Appendable.java
index 098b60c..d22c5a8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Appendable.java
+++ b/crypto/src/main/java/org/conscrypt/Appendable.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* This interface represents the ability of the input stream related classes to provide additional
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java b/crypto/src/main/java/org/conscrypt/ByteArray.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java
rename to crypto/src/main/java/org/conscrypt/ByteArray.java
index 8a000c5..be682de 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ByteArray.java
+++ b/crypto/src/main/java/org/conscrypt/ByteArray.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.util.Arrays;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java b/crypto/src/main/java/org/conscrypt/CertPinManager.java
similarity index 77%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java
rename to crypto/src/main/java/org/conscrypt/CertPinManager.java
index 4cdd8d2..22578fc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertPinManager.java
+++ b/crypto/src/main/java/org/conscrypt/CertPinManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.FileNotFoundException;
@@ -22,8 +22,8 @@
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
-import javax.net.ssl.DefaultHostnameVerifier;
import libcore.io.IoUtils;
import libcore.util.BasicLruCache;
@@ -36,7 +36,6 @@
private final Map<String, PinListEntry> entries = new HashMap<String, PinListEntry>();
private final BasicLruCache<String, String> hostnameCache = new BasicLruCache<String, String>(10);
- private final DefaultHostnameVerifier verifier = new DefaultHostnameVerifier();
private boolean initialized = false;
private static final boolean DEBUG = false;
@@ -166,13 +165,59 @@
continue;
}
// now verify that the CN matches at all
- if (verifier.verifyHostName(hostname, cn)) {
+ if (isHostnameMatchedBy(hostname, cn)) {
bestMatch = cn;
}
}
return bestMatch;
}
+ /**
+ * Returns true if {@code hostName} matches the name or pattern {@code cn}.
+ *
+ * @param hostName lowercase host name.
+ * @param cn certificate host name. May include wildcards like
+ * {@code *.android.com}.
+ */
+ private static boolean isHostnameMatchedBy(String hostName, String cn) {
+ if (hostName == null || hostName.isEmpty() || cn == null || cn.isEmpty()) {
+ return false;
+ }
+
+ cn = cn.toLowerCase(Locale.US);
+
+ if (!cn.contains("*")) {
+ return hostName.equals(cn);
+ }
+
+ if (cn.startsWith("*.") && hostName.regionMatches(0, cn, 2, cn.length() - 2)) {
+ return true; // "*.foo.com" matches "foo.com"
+ }
+
+ int asterisk = cn.indexOf('*');
+ int dot = cn.indexOf('.');
+ if (asterisk > dot) {
+ return false; // malformed; wildcard must be in the first part of
+ // the cn
+ }
+
+ if (!hostName.regionMatches(0, cn, 0, asterisk)) {
+ return false; // prefix before '*' doesn't match
+ }
+
+ int suffixLength = cn.length() - (asterisk + 1);
+ int suffixStart = hostName.length() - suffixLength;
+ if (hostName.indexOf('.', asterisk) < suffixStart) {
+ return false; // wildcard '*' can't match a '.'
+ }
+
+ if (!hostName.regionMatches(suffixStart, cn, asterisk + 1, suffixLength)) {
+ return false; // suffix after '*' doesn't match
+ }
+
+ return true;
+ }
+
private static void log(String s, Exception e) {
if (DEBUG) {
System.out.println("PINFILE: " + s);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java b/crypto/src/main/java/org/conscrypt/CertificateMessage.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
rename to crypto/src/main/java/org/conscrypt/CertificateMessage.java
index 9bc28a0..0c0e092 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateMessage.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateMessage.java
@@ -15,10 +15,9 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
-import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
@@ -158,8 +157,6 @@
/**
* Returns message type
- *
- * @return
*/
@Override
public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java b/crypto/src/main/java/org/conscrypt/CertificateRequest.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
rename to crypto/src/main/java/org/conscrypt/CertificateRequest.java
index f3be44c..6d08cc2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateRequest.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateRequest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.cert.X509Certificate;
@@ -132,8 +132,6 @@
/**
* Returns message type
- *
- * @return
*/
@Override
public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java b/crypto/src/main/java/org/conscrypt/CertificateVerify.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
rename to crypto/src/main/java/org/conscrypt/CertificateVerify.java
index aa4402e..8ba394a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CertificateVerify.java
+++ b/crypto/src/main/java/org/conscrypt/CertificateVerify.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
@@ -82,8 +82,6 @@
/**
* Returns message type
- *
- * @return
*/
@Override
public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java b/crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java
rename to crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
index 29b55a6..dc4f9b7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzer.java
+++ b/crypto/src/main/java/org/conscrypt/ChainStrengthAnalyzer.java
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPublicKey;
-import java.util.List;
public final class ChainStrengthAnalyzer {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java b/crypto/src/main/java/org/conscrypt/CipherSuite.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
rename to crypto/src/main/java/org/conscrypt/CipherSuite.java
index c20a0b9..6d2a3e8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/CipherSuite.java
+++ b/crypto/src/main/java/org/conscrypt/CipherSuite.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.GeneralSecurityException;
import java.util.Hashtable;
@@ -971,7 +971,6 @@
/**
* Returns true if cipher suite is anonymous
- * @return
*/
public boolean isAnonymous() {
if (keyExchange == KEY_EXCHANGE_DH_anon
@@ -984,7 +983,6 @@
/**
* Returns array of supported CipherSuites
- * @return
*/
public static CipherSuite[] getSupported() {
return SUPPORTED_CIPHER_SUITES;
@@ -992,7 +990,6 @@
/**
* Returns array of supported cipher suites names
- * @return
*/
public static String[] getSupportedCipherSuiteNames() {
return SUPPORTED_CIPHER_SUITE_NAMES.clone();
@@ -1000,7 +997,6 @@
/**
* Returns cipher suite name
- * @return
*/
public String getName() {
return name;
@@ -1008,7 +1004,6 @@
/**
* Returns cipher suite code as byte array
- * @return
*/
public byte[] toBytes() {
return cipherSuiteCode;
@@ -1024,7 +1019,6 @@
/**
* Returns cipher algorithm name
- * @return
*/
public String getBulkEncryptionAlgorithm() {
return cipherName;
@@ -1032,7 +1026,6 @@
/**
* Returns cipher block size
- * @return
*/
public int getBlockSize() {
return blockSize;
@@ -1040,7 +1033,6 @@
/**
* Returns MAC algorithm name
- * @return
*/
public String getHmacName() {
return hmacName;
@@ -1048,7 +1040,6 @@
/**
* Returns hash algorithm name
- * @return
*/
public String getHashName() {
return hashName;
@@ -1056,7 +1047,6 @@
/**
* Returns hash size
- * @return
*/
public int getMACLength() {
return hashSize;
@@ -1064,7 +1054,6 @@
/**
* Indicates whether this cipher suite is exportable
- * @return
*/
public boolean isExportable() {
return isExportable;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java b/crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
rename to crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
index 5d2521b..8706ec0 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java
+++ b/crypto/src/main/java/org/conscrypt/ClientHandshakeImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.Key;
@@ -322,7 +322,7 @@
* Processes SSLv2 Hello message.
* SSLv2 client hello message message is an unexpected message
* for client side of handshake protocol.
- * @ see TLS 1.0 spec., E.1. Version 2 client hello
+ * See TLS 1.0 spec., E.1. Version 2 client hello
* @param bytes
*/
@Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java b/crypto/src/main/java/org/conscrypt/ClientHello.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
rename to crypto/src/main/java/org/conscrypt/ClientHello.java
index 1bded5d..2bf9f5f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHello.java
+++ b/crypto/src/main/java/org/conscrypt/ClientHello.java
@@ -15,13 +15,13 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.Arrays;
import libcore.io.Streams;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* Represents Client Hello message
@@ -199,7 +199,6 @@
/**
* Returns message type
- * @return
*/
@Override
public int getType() {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java b/crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
rename to crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
index 2bae8d0..5cad36b 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientKeyExchange.java
+++ b/crypto/src/main/java/org/conscrypt/ClientKeyExchange.java
@@ -15,12 +15,12 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.math.BigInteger;
import libcore.io.Streams;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* Represents client key exchange message
@@ -133,7 +133,6 @@
/**
* Returns message type
- * @return
*/
@Override
public int getType() {
@@ -142,7 +141,6 @@
/**
* Returns true if the message is empty (in case of implicit DH Yc)
- * @return
*/
public boolean isEmpty() {
return (exchange_keys.length == 0);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java b/crypto/src/main/java/org/conscrypt/ClientSessionContext.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
rename to crypto/src/main/java/org/conscrypt/ClientSessionContext.java
index 0b358aa..27a39cf 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/ClientSessionContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.util.HashMap;
import java.util.Map;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java b/crypto/src/main/java/org/conscrypt/ConnectionState.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
rename to crypto/src/main/java/org/conscrypt/ConnectionState.java
index eed6dee..82fbf3c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionState.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionState.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.crypto.Cipher;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java b/crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
rename to crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
index 480d77d..84b8483 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateSSLv3.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionStateSSLv3.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
@@ -52,7 +52,7 @@
/**
* Creates the instance of SSL v3 Connection State. All of the
* security parameters are provided by session object.
- * @param session: the sessin object which incapsulates
+ * @param session the sessin object which incapsulates
* all of the security parameters established by handshake protocol.
* The key calculation for the state is done according
* to the SSL v3 Protocol specification.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java b/crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
rename to crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
index 42169da..a4d9de8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ConnectionStateTLS.java
+++ b/crypto/src/main/java/org/conscrypt/ConnectionStateTLS.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.GeneralSecurityException;
import java.util.Arrays;
@@ -74,7 +74,7 @@
/**
* Creates the instance of TLS v1 Connection State. All of the
* security parameters are provided by session object.
- * @param session: the sessin object which incapsulates
+ * @param session the sessin object which incapsulates
* all of the security parameters established by handshake protocol.
* The key calculation for the state is done according
* to the TLS v 1.0 Protocol specification.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java b/crypto/src/main/java/org/conscrypt/ContentType.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
rename to crypto/src/main/java/org/conscrypt/ContentType.java
index 69704f5..b09f029 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ContentType.java
+++ b/crypto/src/main/java/org/conscrypt/ContentType.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* This class incapsulates the constants determining the
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java b/crypto/src/main/java/org/conscrypt/DHParameters.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
rename to crypto/src/main/java/org/conscrypt/DHParameters.java
index 4988d5e..7a742b2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DHParameters.java
+++ b/crypto/src/main/java/org/conscrypt/DHParameters.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* This class contains well-known primes
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java b/crypto/src/main/java/org/conscrypt/DataStream.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
rename to crypto/src/main/java/org/conscrypt/DataStream.java
index ffc8612..d65b01a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DataStream.java
+++ b/crypto/src/main/java/org/conscrypt/DataStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* This interface represents the ability of the
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java b/crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
index 66b9ebe..c90787f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DefaultSSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/DefaultSSLContextImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
@@ -25,7 +25,7 @@
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.SecureRandom;
-import java.security.Security;
+
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java b/crypto/src/main/java/org/conscrypt/DelegatedTask.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
rename to crypto/src/main/java/org/conscrypt/DelegatedTask.java
index 0e13bc2..8eab2ea 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DelegatedTask.java
+++ b/crypto/src/main/java/org/conscrypt/DelegatedTask.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
* Delegated Runnable task for SSLEngine
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java b/crypto/src/main/java/org/conscrypt/DigitalSignature.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
rename to crypto/src/main/java/org/conscrypt/DigitalSignature.java
index ade2c7a..e24056e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/DigitalSignature.java
+++ b/crypto/src/main/java/org/conscrypt/DigitalSignature.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.DigestException;
import java.security.InvalidKeyException;
@@ -30,7 +30,7 @@
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.net.ssl.SSLException;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* This class represents Signature type, as described in TLS v 1.0 Protocol
@@ -66,17 +66,17 @@
/**
* Create Signature type
- * @param keyExchange
+ * @param algorithm the key algorithm used for the signature
*/
- public DigitalSignature(String authType) {
+ public DigitalSignature(String algorithm) {
try {
sha = MessageDigest.getInstance("SHA-1");
- if ("RSA".equals(authType)) {
+ if ("RSA".equals(algorithm)) {
md5 = MessageDigest.getInstance("MD5");
cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
signature = null;
- } else if ("DSA".equals(authType)) {
+ } else if ("DSA".equals(algorithm)) {
// SignatureAlgorithm is dsa
signature = Signature.getInstance("NONEwithDSA");
cipher = null;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java b/crypto/src/main/java/org/conscrypt/EndOfBufferException.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
rename to crypto/src/main/java/org/conscrypt/EndOfBufferException.java
index 7fe2d7f..acd3417 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
+++ b/crypto/src/main/java/org/conscrypt/EndOfBufferException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java b/crypto/src/main/java/org/conscrypt/EndOfSourceException.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
rename to crypto/src/main/java/org/conscrypt/EndOfSourceException.java
index 3874709..4789cd8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfSourceException.java
+++ b/crypto/src/main/java/org/conscrypt/EndOfSourceException.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java b/crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
rename to crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
index 0f1fe24..e4dab13 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/FileClientSessionCache.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.DataInputStream;
import java.io.File;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java b/crypto/src/main/java/org/conscrypt/Finished.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
rename to crypto/src/main/java/org/conscrypt/Finished.java
index fc89d48..e0b7eaa 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Finished.java
+++ b/crypto/src/main/java/org/conscrypt/Finished.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
@@ -63,7 +63,6 @@
/**
* Returns message type
- * @return
*/
@Override
public int getType() {
@@ -72,7 +71,6 @@
/**
* Returns verify data
- * @return
*/
public byte[] getData() {
return data;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java b/crypto/src/main/java/org/conscrypt/Handshake.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
rename to crypto/src/main/java/org/conscrypt/Handshake.java
index b61a96c..7cee71b 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Handshake.java
+++ b/crypto/src/main/java/org/conscrypt/Handshake.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
*
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java b/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
rename to crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
index ee9f667..0723820 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeIODataStream.java
+++ b/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.PrintStream;
@@ -60,7 +60,7 @@
* TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt.
*/
public class HandshakeIODataStream
- extends SSLInputStream implements org.apache.harmony.xnet.provider.jsse.Appendable, DataStream {
+ extends SSLInputStream implements org.conscrypt.Appendable, DataStream {
// Objects are used to compute digests of data passed
// during the handshake phase
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java b/crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
rename to crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
index f8016f1..73d00ae 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HandshakeProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/HandshakeProtocol.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
@@ -180,7 +180,6 @@
/**
* Start session negotiation
- * @param session
*/
public abstract void start();
@@ -198,7 +197,6 @@
/**
* Returns handshake status
- * @return
*/
public SSLEngineResult.HandshakeStatus getStatus() {
if (io_stream.hasData() || needSendCCSpec ||
@@ -260,8 +258,7 @@
public abstract void unwrapSSLv2(byte[] bytes);
/**
- * Proceses outbound handshake messages
- * @return
+ * Processes outbound handshake messages
*/
public byte[] wrap() {
if (delegatedTaskErr != null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java b/crypto/src/main/java/org/conscrypt/HelloRequest.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
rename to crypto/src/main/java/org/conscrypt/HelloRequest.java
index 69c146c..20efbfd 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/HelloRequest.java
+++ b/crypto/src/main/java/org/conscrypt/HelloRequest.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java b/crypto/src/main/java/org/conscrypt/JSSEProvider.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
rename to crypto/src/main/java/org/conscrypt/JSSEProvider.java
index 58dad45..ad56976 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/JSSEProvider.java
+++ b/crypto/src/main/java/org/conscrypt/JSSEProvider.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.Provider;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java b/crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
similarity index 86%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
index 261f3c7..3ad9be9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/KeyManagerFactoryImpl.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.FileInputStream;
@@ -29,11 +29,11 @@
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactorySpi;
import javax.net.ssl.ManagerFactoryParameters;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* KeyManagerFactory implementation.
- * @see javax.net.ssl.KeyManagerFactorySpi
+ * @see KeyManagerFactorySpi
*/
public class KeyManagerFactoryImpl extends KeyManagerFactorySpi {
@@ -44,11 +44,10 @@
private char[] pwd;
/**
- * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(KeyStore ks, char[]
- * password)
+ * @see KeyManagerFactorySpi#engineInit(KeyStore ks, char[] password)
*/
@Override
- public void engineInit(KeyStore ks, char[] password)
+ protected void engineInit(KeyStore ks, char[] password)
throws KeyStoreException, NoSuchAlgorithmException,
UnrecoverableKeyException {
if (ks != null) {
@@ -93,11 +92,10 @@
}
/**
- * @see javax.net.ssl.KeyManagerFactorySpi#engineInit(ManagerFactoryParameters
- * spec)
+ * @see KeyManagerFactorySpi#engineInit(ManagerFactoryParameters spec)
*/
@Override
- public void engineInit(ManagerFactoryParameters spec)
+ protected void engineInit(ManagerFactoryParameters spec)
throws InvalidAlgorithmParameterException {
throw new InvalidAlgorithmParameterException(
"ManagerFactoryParameters not supported");
@@ -105,10 +103,10 @@
}
/**
- * @see javax.net.ssl.KeyManagerFactorySpi#engineGetKeyManagers()
+ * @see KeyManagerFactorySpi#engineGetKeyManagers()
*/
@Override
- public KeyManager[] engineGetKeyManagers() {
+ protected KeyManager[] engineGetKeyManagers() {
if (keyStore == null) {
throw new IllegalStateException("KeyManagerFactory is not initialized");
}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
rename to crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
index 8ccf687..ed37fd6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/KeyManagerImpl.java
+++ b/crypto/src/main/java/org/conscrypt/KeyManagerImpl.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.net.Socket;
import java.security.KeyStore;
@@ -190,7 +190,7 @@
continue;
}
// check that a certificate in the chain was issued by one of the specified issuers
- loop: for (Certificate certFromChain : chain) {
+ for (Certificate certFromChain : chain) {
if (!(certFromChain instanceof X509Certificate)) {
// skip non-X509Certificates
continue;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java b/crypto/src/main/java/org/conscrypt/Logger.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
rename to crypto/src/main/java/org/conscrypt/Logger.java
index 2fbbef7..9241c8a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Logger.java
+++ b/crypto/src/main/java/org/conscrypt/Logger.java
@@ -15,11 +15,11 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.PrintStream;
import java.util.Locale;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* This class provides debug logging for JSSE provider implementation
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java b/crypto/src/main/java/org/conscrypt/Message.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
rename to crypto/src/main/java/org/conscrypt/Message.java
index bd97136..3b932d0 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/Message.java
+++ b/crypto/src/main/java/org/conscrypt/Message.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
@@ -33,13 +33,11 @@
/**
* Returns message type
- * @return
*/
abstract int getType();
/**
* Returns message length
- * @return
*/
public int length() {
return length;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
rename to crypto/src/main/java/org/conscrypt/NativeCrypto.java
index 9991af4..9094935 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/crypto/src/main/java/org/conscrypt/NativeCrypto.java
@@ -14,22 +14,19 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
-import java.nio.ByteOrder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -40,7 +37,6 @@
import javax.crypto.IllegalBlockSizeException;
import javax.net.ssl.SSLException;
import javax.security.auth.x500.X500Principal;
-import libcore.io.Memory;
/**
* Provides the Java side of our JNI glue for OpenSSL.
@@ -49,6 +45,15 @@
// --- 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 (!"com.android.org.conscrypt".equals(NativeCrypto.class.getPackage().getName())) {
+ System.loadLibrary("conscrypt_jni");
+ }
+
clinit();
}
@@ -340,7 +345,11 @@
private static int X509_NAME_hash(X500Principal principal, String algorithm) {
try {
byte[] digest = MessageDigest.getInstance(algorithm).digest(principal.getEncoded());
- return Memory.peekInt(digest, 0, ByteOrder.LITTLE_ENDIAN);
+ int offset = 0;
+ return (((digest[offset++] & 0xff) << 0) |
+ ((digest[offset++] & 0xff) << 8) |
+ ((digest[offset++] & 0xff) << 16) |
+ ((digest[offset ] & 0xff) << 24));
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
@@ -437,6 +446,8 @@
public static native int get_X509_ex_flags(long x509ctx);
+ public static native int X509_check_issued(long ctx, long ctx2);
+
// --- X509 EXFLAG ---------------------------------------------------------
public static final int EXFLAG_CA = 0x10;
@@ -762,27 +773,7 @@
public static native byte[] SSL_get_tls_channel_id(long ssl) throws SSLException;
- public static native void SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(long ssl, long pkey)
- throws SSLException;
-
- public static native void SSL_use_PKCS8_PrivateKey_for_tls_channel_id(
- long ssl, byte[] pkcs8EncodedPrivateKey) throws SSLException;
-
- public static void SSL_set1_tls_channel_id(long ssl, PrivateKey privateKey)
- throws SSLException {
- if (privateKey == null) {
- throw new NullPointerException("privateKey == null");
- } else if (privateKey instanceof OpenSSLECPrivateKey) {
- OpenSSLKey openSslPrivateKey = ((OpenSSLECPrivateKey) privateKey).getOpenSSLKey();
- SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(ssl, openSslPrivateKey.getPkeyContext());
- } else if ("PKCS#8".equals(privateKey.getFormat())) {
- byte[] pkcs8EncodedKey = privateKey.getEncoded();
- SSL_use_PKCS8_PrivateKey_for_tls_channel_id(ssl, pkcs8EncodedKey);
- } else {
- throw new SSLException("Unsupported Channel ID private key type:" +
- " class: " + privateKey.getClass() + ", format: " + privateKey.getFormat());
- }
- }
+ public static native void SSL_set1_tls_channel_id(long ssl, long pkey);
public static byte[][] encodeCertificates(Certificate[] certificates)
throws CertificateEncodingException {
@@ -795,21 +786,10 @@
public static native void SSL_use_certificate(long ssl, byte[][] asn1DerEncodedCertificateChain);
- public static native void SSL_use_OpenSSL_PrivateKey(long ssl, long pkey);
-
- public static native void SSL_use_PrivateKey(long ssl, byte[] pkcs8EncodedPrivateKey);
+ public static native void SSL_use_PrivateKey(long ssl, long pkey);
public static native void SSL_check_private_key(long ssl) throws SSLException;
- public static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
- throws CertificateEncodingException {
- byte[][] principalBytes = new byte[certificates.length][];
- for (int i = 0; i < certificates.length; i++) {
- principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
- }
- return principalBytes;
- }
-
public static native void SSL_set_client_CA_list(long ssl, byte[][] asn1DerEncodedX500Principals);
public static native long SSL_get_mode(long ssl);
@@ -972,14 +952,29 @@
public static native void SSL_CTX_disable_npn(long sslCtxNativePointer);
/**
- * Returns the sslSessionNativePointer of the negotiated session
+ * For clients, sets the list of supported ALPN protocols in wire-format
+ * (length-prefixed 8-bit strings) on an SSL context.
+ */
+ public static native int SSL_CTX_set_alpn_protos(long sslCtxPointer, byte[] protos);
+
+ /**
+ * Returns the selected ALPN protocol. If the server did not select a
+ * protocol, {@code null} will be returned.
+ */
+ public static native byte[] SSL_get0_alpn_selected(long sslPointer);
+
+ /**
+ * Returns the sslSessionNativePointer of the negotiated session. If this is
+ * a server negotiation, supplying the {@code alpnProtocols} will enable
+ * ALPN negotiation.
*/
public static native int SSL_do_handshake(long sslNativePointer,
FileDescriptor fd,
SSLHandshakeCallbacks shc,
int timeoutMillis,
boolean client_mode,
- byte[] npnProtocols)
+ byte[] npnProtocols,
+ byte[] alpnProtocols)
throws SSLException, SocketTimeoutException, CertificateException;
public static native byte[] SSL_get_npn_negotiated_protocol(long sslNativePointer);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java b/crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
index 54e5798..26971d5 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLBIOInputStream.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.FilterInputStream;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
index 6ca8835..632f9e2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipher.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipher.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
@@ -31,7 +31,6 @@
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Locale;
-
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
@@ -41,8 +40,7 @@
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
-
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
public abstract class OpenSSLCipher extends CipherSpi {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
index eb99334..ffbcad4 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipherContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
class OpenSSLCipherContext {
private final long context;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java b/crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
index ddf2e0d..9e2f426 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLCipherRSA.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLCipherRSA.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
@@ -33,6 +33,7 @@
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
+import java.util.Locale;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.CipherSpi;
@@ -40,7 +41,7 @@
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
public abstract class OpenSSLCipherRSA extends CipherSpi {
/**
@@ -85,7 +86,7 @@
@Override
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
- final String modeUpper = mode.toUpperCase();
+ final String modeUpper = mode.toUpperCase(Locale.ROOT);
if ("NONE".equals(modeUpper) || "ECB".equals(modeUpper)) {
return;
}
@@ -95,7 +96,7 @@
@Override
protected void engineSetPadding(String padding) throws NoSuchPaddingException {
- final String paddingUpper = padding.toUpperCase();
+ final String paddingUpper = padding.toUpperCase(Locale.ROOT);
if ("PKCS1PADDING".equals(paddingUpper)) {
this.padding = NativeCrypto.RSA_PKCS1_PADDING;
return;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
index b4e4a46..6b0e5f9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLContextImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.GeneralSecurityException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
index efa4747..a9f7067 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyFactory.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
index aa0b317..3428fcc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAKeyPairGenerator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
index df9968b..fd0edf7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAParams.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAParams.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.interfaces.DSAParams;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
index df62c6d..0fc4db7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPrivateKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
index be9ff83..1c0bf74 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDSAPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDSAPublicKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
index b3bd1a0..b11a862 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLDigestContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLDigestContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
public class OpenSSLDigestContext {
private final long context;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java b/crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
index 5146156..0d8729c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECDHKeyAgreement.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -24,7 +24,6 @@
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
-
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
index 173ce79..f7f52a6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECGroupContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECGroupContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
index e4673a5..b39a611 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyFactory.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
index bea46e6..21c8984 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECKeyPairGenerator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
index 7c5c067..49bdaf1 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPointContext.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPointContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.spec.ECPoint;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
index b0be998..a4b41db 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPrivateKey.java
@@ -14,14 +14,13 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
-import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.interfaces.ECPrivateKey;
import java.security.spec.ECParameterSpec;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
index b591336..8f3a0c6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLECPublicKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java b/crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
index 4e02aad..380e73f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLEngine.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLEngine.java
@@ -14,12 +14,11 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
-
import javax.crypto.SecretKey;
public class OpenSSLEngine {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLKey.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLKey.java
index 921a4b6..fa9a258 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLKey.java
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
+import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
-
import javax.crypto.SecretKey;
public class OpenSSLKey {
@@ -65,6 +65,18 @@
return alias;
}
+ public static OpenSSLKey fromPrivateKey(PrivateKey key) throws InvalidKeyException {
+ if (key instanceof OpenSSLKeyHolder) {
+ return ((OpenSSLKeyHolder) key).getOpenSSLKey();
+ }
+
+ if ("PKCS#8".equals(key.getFormat())) {
+ return new OpenSSLKey(NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(key.getEncoded()));
+ } else {
+ throw new InvalidKeyException("Unknown key format " + key.getFormat());
+ }
+ }
+
public PublicKey getPublicKey() throws NoSuchAlgorithmException {
switch (NativeCrypto.EVP_PKEY_type(ctx)) {
case NativeCrypto.EVP_PKEY_RSA:
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
similarity index 93%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
index 548e9c5..09af21c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLKeyHolder.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
public interface OpenSSLKeyHolder {
public OpenSSLKey getOpenSSLKey();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java b/crypto/src/main/java/org/conscrypt/OpenSSLMac.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLMac.java
index 697af5a..824e6b9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMac.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLMac.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java b/crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
index 9d59a7c..763ff65 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLMessageDigestJDK.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLMessageDigestJDK.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
diff --git a/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
new file mode 100644
index 0000000..7314478
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLProvider.java
@@ -0,0 +1,238 @@
+/*
+ * 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 org.conscrypt;
+
+import java.security.Provider;
+
+/**
+ * Provider that goes through OpenSSL for operations.
+ * <p>
+ * Every algorithm should have its IANA assigned OID as an alias. See the following URLs for each type:
+ * <ul>
+ * <li><a href="http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml">Hash functions</a></li>
+ * <li><a href="http://www.iana.org/assignments/dssc/dssc.xml">Signature algorithms</a></li>
+ * <li><a href="http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html">NIST cryptographic algorithms</a></li>
+ * </ul>
+ */
+public final class OpenSSLProvider extends Provider {
+ private static final long serialVersionUID = 2996752495318905136L;
+
+ public static final String PROVIDER_NAME = "AndroidOpenSSL";
+
+ public OpenSSLProvider() {
+ super(PROVIDER_NAME, 1.0, "Android's OpenSSL-backed security provider");
+
+ final String prefix = getClass().getPackage().getName() + ".";
+
+ /* === SSL Contexts === */
+ final String classOpenSSLContextImpl = prefix + "OpenSSLContextImpl";
+ put("SSLContext.SSL", classOpenSSLContextImpl);
+ put("SSLContext.SSLv3", classOpenSSLContextImpl);
+ put("SSLContext.TLS", classOpenSSLContextImpl);
+ put("SSLContext.TLSv1", classOpenSSLContextImpl);
+ put("SSLContext.TLSv1.1", classOpenSSLContextImpl);
+ put("SSLContext.TLSv1.2", classOpenSSLContextImpl);
+ put("SSLContext.Default", prefix + "DefaultSSLContextImpl");
+
+ /* === Message Digests === */
+ put("MessageDigest.SHA-1", prefix + "OpenSSLMessageDigestJDK$SHA1");
+ put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
+ put("Alg.Alias.MessageDigest.SHA", "SHA-1");
+ put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1");
+
+ put("MessageDigest.SHA-256", prefix + "OpenSSLMessageDigestJDK$SHA256");
+ put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
+ put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
+
+ put("MessageDigest.SHA-384", prefix + "OpenSSLMessageDigestJDK$SHA384");
+ put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
+ put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
+
+ put("MessageDigest.SHA-512", prefix + "OpenSSLMessageDigestJDK$SHA512");
+ put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
+ put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
+
+ // iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) md5(5)
+ put("MessageDigest.MD5", prefix + "OpenSSLMessageDigestJDK$MD5");
+ put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5");
+
+ /* == KeyPairGenerators == */
+ put("KeyPairGenerator.RSA", prefix + "OpenSSLRSAKeyPairGenerator");
+ put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");
+
+ put("KeyPairGenerator.DSA", prefix + "OpenSSLDSAKeyPairGenerator");
+
+ put("KeyPairGenerator.EC", prefix + "OpenSSLECKeyPairGenerator");
+
+ /* == KeyFactory == */
+ put("KeyFactory.RSA", prefix + "OpenSSLRSAKeyFactory");
+ put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA");
+
+ put("KeyFactory.DSA", prefix + "OpenSSLDSAKeyFactory");
+
+ put("KeyFactory.EC", prefix + "OpenSSLECKeyFactory");
+
+ /* == KeyAgreement == */
+ put("KeyAgreement.ECDH", prefix + "OpenSSLECDHKeyAgreement");
+
+ /* == Signatures == */
+ put("Signature.MD5WithRSA", prefix + "OpenSSLSignature$MD5RSA");
+ put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5WithRSA");
+ put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSA");
+
+ put("Signature.SHA1WithRSA", prefix + "OpenSSLSignature$SHA1RSA");
+ put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1WithRSA");
+ put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSA");
+ put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1WithRSA");
+
+ put("Signature.SHA256WithRSA", prefix + "OpenSSLSignature$SHA256RSA");
+ put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256WithRSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
+ "SHA256WithRSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
+ "SHA256WithRSA");
+
+ put("Signature.SHA384WithRSA", prefix + "OpenSSLSignature$SHA384RSA");
+ put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384WithRSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
+ "SHA384WithRSA");
+
+ put("Signature.SHA512WithRSA", prefix + "OpenSSLSignature$SHA512RSA");
+ put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512WithRSA");
+ put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512WithRSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
+ "SHA512WithRSA");
+
+ put("Signature.SHA1withDSA", prefix + "OpenSSLSignature$SHA1DSA");
+ put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.DSA", "SHA1withDSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "SHA1withDSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA");
+ put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
+ put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
+
+ put("Signature.NONEwithRSA", prefix + "OpenSSLSignatureRawRSA");
+
+ put("Signature.ECDSA", prefix + "OpenSSLSignature$SHA1ECDSA");
+ put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
+ put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
+ // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
+ put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "ECDSA");
+
+ // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
+ put("Signature.SHA256withECDSA", prefix + "OpenSSLSignature$SHA256ECDSA");
+ // ecdsa-with-SHA256(2)
+ put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.10045.2.1", "SHA256withECDSA");
+
+ put("Signature.SHA384withECDSA", prefix + "OpenSSLSignature$SHA384ECDSA");
+ // ecdsa-with-SHA384(3)
+ put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.10045.2.1", "SHA384withECDSA");
+
+ put("Signature.SHA512withECDSA", prefix + "OpenSSLSignature$SHA512ECDSA");
+ // ecdsa-with-SHA512(4)
+ put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
+ put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.10045.2.1", "SHA512withECDSA");
+
+ /* === SecureRandom === */
+ /*
+ * We have to specify SHA1PRNG because various documentation mentions
+ * that algorithm by name instead of just recommending calling
+ * "new SecureRandom()"
+ */
+ put("SecureRandom.SHA1PRNG", prefix + "OpenSSLRandom");
+ put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
+
+ /* === Cipher === */
+ put("Cipher.RSA/ECB/NoPadding", prefix + "OpenSSLCipherRSA$Raw");
+ put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
+ put("Cipher.RSA/ECB/PKCS1Padding", prefix + "OpenSSLCipherRSA$PKCS1");
+ put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
+
+ /*
+ * OpenSSL only supports a subset of modes, so we'll name them
+ * explicitly here.
+ */
+ put("Cipher.AES/ECB/NoPadding", prefix + "OpenSSLCipher$AES$ECB$NoPadding");
+ put("Cipher.AES/ECB/PKCS5Padding", prefix + "OpenSSLCipher$AES$ECB$PKCS5Padding");
+ put("Cipher.AES/CBC/NoPadding", prefix + "OpenSSLCipher$AES$CBC$NoPadding");
+ put("Cipher.AES/CBC/PKCS5Padding", prefix + "OpenSSLCipher$AES$CBC$PKCS5Padding");
+ put("Cipher.AES/CFB/NoPadding", prefix + "OpenSSLCipher$AES$CFB$NoPadding");
+ put("Cipher.AES/CFB/PKCS5Padding", prefix + "OpenSSLCipher$AES$CFB$PKCS5Padding");
+ put("Cipher.AES/CTR/NoPadding", prefix + "OpenSSLCipher$AES$CTR$NoPadding");
+ put("Cipher.AES/CTR/PKCS5Padding", prefix + "OpenSSLCipher$AES$CTR$PKCS5Padding");
+ put("Cipher.AES/OFB/NoPadding", prefix + "OpenSSLCipher$AES$OFB$NoPadding");
+ put("Cipher.AES/OFB/PKCS5Padding", prefix + "OpenSSLCipher$AES$OFB$PKCS5Padding");
+
+ put("Cipher.DESEDE/CBC/NoPadding", prefix + "OpenSSLCipher$DESEDE$CBC$NoPadding");
+ put("Cipher.DESEDE/CBC/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$CBC$PKCS5Padding");
+ put("Cipher.DESEDE/CFB/NoPadding", prefix + "OpenSSLCipher$DESEDE$CFB$NoPadding");
+ put("Cipher.DESEDE/CFB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$CFB$PKCS5Padding");
+ put("Cipher.DESEDE/ECB/NoPadding", prefix + "OpenSSLCipher$DESEDE$ECB$NoPadding");
+ put("Cipher.DESEDE/ECB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$ECB$PKCS5Padding");
+ put("Cipher.DESEDE/OFB/NoPadding", prefix + "OpenSSLCipher$DESEDE$OFB$NoPadding");
+ put("Cipher.DESEDE/OFB/PKCS5Padding", prefix + "OpenSSLCipher$DESEDE$OFB$PKCS5Padding");
+
+ put("Cipher.ARC4", prefix + "OpenSSLCipher$ARC4");
+
+ /* === Mac === */
+
+ put("Mac.HmacMD5", prefix + "OpenSSLMac$HmacMD5");
+
+ // PKCS#2 - iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2)
+ // http://www.oid-info.com/get/1.2.840.113549.2
+
+ // HMAC-SHA-1 PRF (7)
+ put("Mac.HmacSHA1", prefix + "OpenSSLMac$HmacSHA1");
+ put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
+ put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
+ put("Alg.Alias.Mac.HMAC/SHA1", "HmacSHA1");
+
+ // id-hmacWithSHA256 (9)
+ put("Mac.HmacSHA256", prefix + "OpenSSLMac$HmacSHA256");
+ put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
+ put("Alg.Alias.Mac.HMAC-SHA256", "HmacSHA256");
+ put("Alg.Alias.Mac.HMAC/SHA256", "HmacSHA256");
+
+ // id-hmacWithSHA384 (10)
+ put("Mac.HmacSHA384", prefix + "OpenSSLMac$HmacSHA384");
+ put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
+ put("Alg.Alias.Mac.HMAC-SHA384", "HmacSHA384");
+ put("Alg.Alias.Mac.HMAC/SHA384", "HmacSHA384");
+
+ // id-hmacWithSHA384 (11)
+ put("Mac.HmacSHA512", prefix + "OpenSSLMac$HmacSHA512");
+ put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
+ put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
+ put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
+
+ /* === Certificate === */
+
+ put("CertificateFactory.X509", prefix + "OpenSSLX509CertificateFactory");
+ put("Alg.Alias.CertificateFactory.X.509", "X509");
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
index 9c61abd..c785ac6 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyFactory.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidKeyException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
index 2d19d4e..a00219f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAKeyPairGenerator.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAKeyPairGenerator.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
index c5254ad..1cbf5de 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateCrtKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateCrtKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
index c0e0848..20db293 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPrivateKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPrivateKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
index 08b1920..4bbd7e3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRSAPublicKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRSAPublicKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.ObjectInputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java b/crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
index fd011f0..1683bb8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLRandom.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLRandom.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.Serializable;
import java.security.SecureRandomSpi;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java b/crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
index 1bc59dc..193356e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSecretKey.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSecretKey.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.NotSerializableException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
index c3cdaad..d14e921 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketFactoryImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
index 9744fe0..4c1f709 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLServerSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLServerSocketImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
@@ -233,7 +233,7 @@
+ "to support the enabled cipher suites.");
}
- private boolean checkForPrivateKey(String keyType, Class keyClass) {
+ private boolean checkForPrivateKey(String keyType, Class<?> keyClass) {
String alias = sslParameters.getKeyManager().chooseServerAlias(keyType, null, null);
if (alias == null) {
return false;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
index 1465027..3b7328d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSessionImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.Principal;
@@ -193,9 +193,9 @@
* @return an array of X509 certificates (the peer's one first and then
* eventually that of the certification authority) or null if no
* certificate were used during the SSL connection.
- * @throws <code>SSLPeerUnverifiedCertificateException</code> if either a
- * not X509 certificate was used (i.e. Kerberos certificates) or the
- * peer could not be verified.
+ * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+ * was used (i.e. Kerberos certificates) or the peer could not
+ * be verified.
*/
public javax.security.cert.X509Certificate[] getPeerCertificateChain()
throws SSLPeerUnverifiedException {
@@ -240,9 +240,9 @@
* @return an array of X509 certificates (the peer's one first and then
* eventually that of the certification authority) or null if no
* certificate were used during the SSL connection.
- * @throws <code>SSLPeerUnverifiedException</code> if either a not X509
- * certificate was used (i.e. Kerberos certificates) or the peer
- * could not be verified.
+ * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+ * was used (i.e. Kerberos certificates) or the peer could not
+ * be verified.
*/
public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
checkPeerCertificatesPresent();
@@ -263,9 +263,8 @@
* handshake phase is returned by this method.
* @return a X500Principal of the last certificate for X509-based
* cipher suites.
- * @throws <code>SSLPeerUnverifiedException</code> if either a not X509
- * certificate was used (i.e. Kerberos certificates) or the
- * peer does not exist.
+ * @throws SSLPeerUnverifiedException if either a non-X.509 certificate
+ * was used (i.e. Kerberos certificates) or the peer does not exist.
*
*/
public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
@@ -371,7 +370,7 @@
* @param name the name of the binding to find.
* @return the value bound to that name, or null if the binding does not
* exist.
- * @throws <code>IllegalArgumentException</code> if the argument is null.
+ * @throws IllegalArgumentException if the argument is null.
*/
public Object getValue(String name) {
if (name == null) {
@@ -401,8 +400,7 @@
* accepted!)
* @param value data object that shall be bound to
* name.
- * @throws <code>IllegalArgumentException</code> if one or both
- * argument(s) is null.
+ * @throws IllegalArgumentException if one or both argument(s) is null.
*/
public void putValue(String name, Object value) {
if (name == null || value == null) {
@@ -428,7 +426,7 @@
*
* @param name the name of the link (no null are
* accepted!)
- * @throws <code>IllegalArgumentException</code> if the argument is null.
+ * @throws IllegalArgumentException if the argument is null.
*/
public void removeValue(String name) {
if (name == null) {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java b/crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
index 34115ea..8576010 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignature.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSignature.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java b/crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
index e5d33b3..9c4e4ad 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureRawRSA.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSignatureRawRSA.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
@@ -26,7 +26,6 @@
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
-import java.util.Arrays;
/**
* Implements the JDK Signature interface needed for RAW RSA signature
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
index 41c58b6..72fd89f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketFactoryImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
similarity index 92%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
index ea56afb..7c5d78f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import dalvik.system.BlockGuard;
import dalvik.system.CloseGuard;
@@ -25,6 +25,7 @@
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
+import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.CertificateEncodingException;
@@ -48,7 +49,6 @@
import libcore.io.Libcore;
import libcore.io.Streams;
import libcore.io.StructTimeval;
-import org.apache.harmony.security.provider.cert.X509CertImpl;
/**
* Implementation of the class OpenSSLSocketImpl based on OpenSSL.
@@ -72,6 +72,7 @@
private final Object writeLock = new Object();
private SSLParametersImpl sslParameters;
private byte[] npnProtocols;
+ private byte[] alpnProtocols;
private String[] enabledProtocols;
private String[] enabledCipherSuites;
private boolean useSessionTickets;
@@ -79,7 +80,7 @@
/** Whether the TLS Channel ID extension is enabled. This field is server-side only. */
private boolean channelIdEnabled;
/** Private key for the TLS Channel ID extension. This field is client-side only. */
- private PrivateKey channelIdPrivateKey;
+ private OpenSSLKey channelIdPrivateKey;
private OpenSSLSessionImpl sslSession;
private final Socket socket;
private boolean autoClose;
@@ -280,6 +281,10 @@
NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer);
}
+ if (client && alpnProtocols != null) {
+ NativeCrypto.SSL_CTX_set_alpn_protos(sslCtxNativePointer, alpnProtocols);
+ }
+
// setup server certificates and private keys.
// clients will receive a call back to request certificates.
if (!client) {
@@ -363,7 +368,7 @@
if (issuers != null && issuers.length != 0) {
byte[][] issuersBytes;
try {
- issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers);
+ issuersBytes = encodeIssuerX509Principals(issuers);
} catch (CertificateEncodingException e) {
throw new IOException("Problem encoding principals", e);
}
@@ -381,14 +386,16 @@
}
// TLS Channel ID
- if (client) {
- // Client-side TLS Channel ID
- if (channelIdPrivateKey != null) {
- NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, channelIdPrivateKey);
- }
- } else {
- // Server-side TLS Channel ID
- if (channelIdEnabled) {
+ if (channelIdEnabled) {
+ if (client) {
+ // Client-side TLS Channel ID
+ if (channelIdPrivateKey == null) {
+ throw new SSLHandshakeException("Invalid TLS channel ID key specified");
+ }
+ NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer,
+ channelIdPrivateKey.getPkeyContext());
+ } else {
+ // Server-side TLS Channel ID
NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer);
}
}
@@ -396,7 +403,8 @@
int sslSessionNativePointer;
try {
sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer,
- socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols);
+ socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols,
+ client ? null : alpnProtocols);
} catch (CertificateException e) {
SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage());
wrapper.initCause(e);
@@ -446,6 +454,15 @@
}
}
+ private static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates)
+ throws CertificateEncodingException {
+ byte[][] principalBytes = new byte[certificates.length][];
+ for (int i = 0; i < certificates.length; i++) {
+ principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded();
+ }
+ return principalBytes;
+ }
+
String getPeerHostName() {
if (wrappedHost != null) {
return wrappedHost;
@@ -471,7 +488,7 @@
}
X509Certificate[] certificates = new X509Certificate[certificatesBytes.length];
for (int i = 0; i < certificatesBytes.length; i++) {
- certificates[i] = new X509CertImpl(certificatesBytes[i]);
+ certificates[i] = OpenSSLX509Certificate.fromX509Der(certificatesBytes[i]);
}
return certificates;
}
@@ -489,14 +506,11 @@
return;
}
- if (privateKey instanceof OpenSSLKeyHolder) {
- OpenSSLKey key = ((OpenSSLKeyHolder) privateKey).getOpenSSLKey();
- NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext());
- } else if ("PKCS#8".equals(privateKey.getFormat())) {
- byte[] privateKeyBytes = privateKey.getEncoded();
- NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
- } else {
- throw new SSLException("Unsupported PrivateKey format: " + privateKey.getFormat());
+ try {
+ final OpenSSLKey key = OpenSSLKey.fromPrivateKey(privateKey);
+ NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext());
+ } catch (InvalidKeyException e) {
+ throw new SSLException(e);
}
byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
@@ -585,7 +599,7 @@
}
X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
for (int i = 0; i < bytes.length; i++) {
- peerCertificateChain[i] = new X509CertImpl(bytes[i]);
+ peerCertificateChain[i] = OpenSSLX509Certificate.fromX509Der(bytes[i]);
}
boolean client = sslParameters.getUseClientMode();
if (client) {
@@ -871,7 +885,17 @@
"Could not change Channel ID private key after the initial handshake has"
+ " begun.");
}
- this.channelIdPrivateKey = privateKey;
+ if (privateKey == null) {
+ this.channelIdEnabled = false;
+ this.channelIdPrivateKey = null;
+ } else {
+ this.channelIdEnabled = true;
+ try {
+ this.channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey);
+ } catch (InvalidKeyException e) {
+ // Will have error in startHandshake
+ }
+ }
}
@Override public boolean getUseClientMode() {
@@ -1068,6 +1092,14 @@
}
/**
+ * Returns the protocol agreed upon by client and server, or {@code null} if
+ * no protocol was agreed upon.
+ */
+ public byte[] getAlpnSelectedProtocol() {
+ return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer);
+ }
+
+ /**
* Sets the list of protocols this peer is interested in. If null no
* protocols will be used.
*
@@ -1082,4 +1114,21 @@
}
this.npnProtocols = npnProtocols;
}
+
+ /**
+ * Sets the list of protocols this peer is interested in. If the list is
+ * {@code null}, no protocols will be used.
+ *
+ * @param alpnProtocols a non-empty array of protocol names. From
+ * SSL_select_next_proto, "vector of 8-bit, length prefixed byte
+ * strings. The length byte itself is not included in the length.
+ * A byte string of length 0 is invalid. No byte string may be
+ * truncated.".
+ */
+ public void setAlpnProtocols(byte[] alpnProtocols) {
+ if (alpnProtocols != null && alpnProtocols.length == 0) {
+ throw new IllegalArgumentException("alpnProtocols.length == 0");
+ }
+ this.alpnProtocols = alpnProtocols;
+ }
}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
index df65d12..b6f43fa 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSocketImplWrapper.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLSocketImplWrapper.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
index 04418c7..56b99cc 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRL.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRL.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import org.apache.harmony.security.utils.AlgNameMapper;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
-
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -43,7 +42,6 @@
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
-
import javax.security.auth.x500.X500Principal;
public class OpenSSLX509CRL extends X509CRL {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
index 4965200..470cc98 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CRLEntry.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CRLEntry.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.ByteArrayOutputStream;
import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
index a96c361..57568b8 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertPath.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertPath.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
-
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
@@ -31,6 +29,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
public class OpenSSLX509CertPath extends CertPath {
private static final byte[] PKCS7_MARKER = "-----BEGIN PKCS7".getBytes();
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
index daeb049..b1cd986 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509Certificate.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509Certificate.java
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
-
-import org.apache.harmony.security.utils.AlgNameMapper;
-import org.apache.harmony.security.x509.X509PublicKey;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLX509CertificateFactory.ParsingException;
+package org.conscrypt;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -49,8 +45,9 @@
import java.util.List;
import java.util.Set;
import java.util.TimeZone;
-
import javax.security.auth.x500.X500Principal;
+import org.apache.harmony.security.utils.AlgNameMapper;
+import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException;
public class OpenSSLX509Certificate extends X509Certificate {
private final long mContext;
@@ -61,6 +58,7 @@
public static OpenSSLX509Certificate fromX509DerInputStream(InputStream is)
throws ParsingException {
+ @SuppressWarnings("resource")
final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
try {
@@ -86,6 +84,7 @@
public static List<OpenSSLX509Certificate> fromPkcs7DerInputStream(InputStream is)
throws ParsingException {
+ @SuppressWarnings("resource")
OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
final long[] certRefs;
@@ -114,6 +113,7 @@
public static OpenSSLX509Certificate fromX509PemInputStream(InputStream is)
throws ParsingException {
+ @SuppressWarnings("resource")
final OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
try {
@@ -131,6 +131,7 @@
public static List<OpenSSLX509Certificate> fromPkcs7PemInputStream(InputStream is)
throws ParsingException {
+ @SuppressWarnings("resource")
OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is);
final long[] certRefs;
@@ -412,7 +413,7 @@
* We couldn't find anything else, so just return a nearly-unusable
* X.509-encoded key.
*/
- return new X509PublicKey(oid, encoded, null);
+ return new X509PublicKey(oid, encoded);
}
@Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java
rename to crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
index ca79785..75fdedb 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLX509CertificateFactory.java
+++ b/crypto/src/main/java/org/conscrypt/OpenSSLX509CertificateFactory.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java b/crypto/src/main/java/org/conscrypt/PRF.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
rename to crypto/src/main/java/org/conscrypt/PRF.java
index 6013d38..afbbb45 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PRF.java
+++ b/crypto/src/main/java/org/conscrypt/PRF.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java b/crypto/src/main/java/org/conscrypt/PinEntryException.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
rename to crypto/src/main/java/org/conscrypt/PinEntryException.java
index 8b74514..8c651db 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
+++ b/crypto/src/main/java/org/conscrypt/PinEntryException.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
// public for testing by CertPinManagerTest
public class PinEntryException extends Exception {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java
rename to crypto/src/main/java/org/conscrypt/PinFailureLogger.java
index 40b1838..67bbc1f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinFailureLogger.java
+++ b/crypto/src/main/java/org/conscrypt/PinFailureLogger.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java b/crypto/src/main/java/org/conscrypt/PinListEntry.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java
rename to crypto/src/main/java/org/conscrypt/PinListEntry.java
index c05a391..a401700 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinListEntry.java
+++ b/crypto/src/main/java/org/conscrypt/PinListEntry.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.math.BigInteger;
import java.security.MessageDigest;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java b/crypto/src/main/java/org/conscrypt/PinManagerException.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java
rename to crypto/src/main/java/org/conscrypt/PinManagerException.java
index 74b3c65..e52ae83 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinManagerException.java
+++ b/crypto/src/main/java/org/conscrypt/PinManagerException.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
class PinManagerException extends Exception {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java b/crypto/src/main/java/org/conscrypt/ProtocolVersion.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
rename to crypto/src/main/java/org/conscrypt/ProtocolVersion.java
index 230f9fe..4e2555c 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ProtocolVersion.java
+++ b/crypto/src/main/java/org/conscrypt/ProtocolVersion.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.util.Hashtable;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java b/crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
rename to crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
index c945dbb..d2834d3 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLBufferedInput.java
+++ b/crypto/src/main/java/org/conscrypt/SSLBufferedInput.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.nio.ByteBuffer;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java b/crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
rename to crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
index 8a73fa5..d070a02 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLClientSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/SSLClientSessionCache.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.net.ssl.SSLSession;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java b/crypto/src/main/java/org/conscrypt/SSLContextImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLContextImpl.java
index 0e1e130..75aed4f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLContextImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLContextImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.GeneralSecurityException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java b/crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
similarity index 95%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
index b827016..f2cb77d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineAppData.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineAppData.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.nio.ByteBuffer;
import javax.net.ssl.SSLException;
@@ -24,7 +24,7 @@
* This class is used to retrieve the application data
* arrived for the SSLEngine.
*/
-public class SSLEngineAppData implements org.apache.harmony.xnet.provider.jsse.Appendable {
+public class SSLEngineAppData implements Appendable {
/**
* Buffer containing received application data.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java b/crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
index e209dd1..f4a2d2d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineDataStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineDataStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.nio.ByteBuffer;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java b/crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
index 7f01c8a..3ed9980 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLEngineImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLEngineImpl.java
@@ -15,8 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
-
+package org.conscrypt;
import java.io.IOException;
import java.nio.BufferUnderflowException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java b/crypto/src/main/java/org/conscrypt/SSLInputStream.java
similarity index 92%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLInputStream.java
index 2a6c5d6..c8a5eca 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLInputStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
@@ -38,9 +38,9 @@
* exception, not return -1. The type of exception depends
* on implementation. It was done for simplifying and speeding
* up of processing of such cases.
- * @see org.apache.harmony.xnet.provider.jsse.SSLStreamedInput#read()
- * @see org.apache.harmony.xnet.provider.jsse.SSLBufferedInput#read()
- * @see org.apache.harmony.xnet.provider.jsse.HandshakeIODataStream#read()
+ * @see org.conscrypt.SSLStreamedInput#read()
+ * @see org.conscrypt.SSLBufferedInput#read()
+ * @see org.conscrypt.HandshakeIODataStream#read()
*/
@Override
public abstract int read() throws IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java b/crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
index 287f9f3..21b8ae2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLParametersImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLParametersImpl.java
@@ -15,9 +15,8 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
-import org.apache.harmony.xnet.provider.jsse.TrustManagerImpl;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java b/crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
rename to crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
index e9f77f72..24b6c61 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLRecordProtocol.java
+++ b/crypto/src/main/java/org/conscrypt/SSLRecordProtocol.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import javax.net.ssl.SSLProtocolException;
@@ -82,7 +82,7 @@
// alert protocol to indicate alerts occurred/received
private AlertProtocol alertProtocol;
// application data object to which application data will be transmitted
- private org.apache.harmony.xnet.provider.jsse.Appendable appData;
+ private Appendable appData;
// connection state holding object
private ConnectionState
activeReadState, activeWriteState, pendingConnectionState;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java b/crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
index 32a0e72..a380ce9 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSessionCache.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSessionCache.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.net.ssl.SSLSession;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
index 22872f8..5b16f85 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSocketFactoryImpl.java
@@ -15,14 +15,14 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.security.KeyManagementException;
import javax.net.ssl.SSLServerSocketFactory;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* Implementation of SSLServerSocketFactory.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java b/crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
index 477d03d..a30e3b4 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLServerSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLServerSocketImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java b/crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
index 46834ad..9631b1e 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSessionImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSessionImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.Principal;
import java.security.SecureRandom;
@@ -29,7 +29,7 @@
import javax.net.ssl.SSLSessionBindingEvent;
import javax.net.ssl.SSLSessionBindingListener;
import javax.net.ssl.SSLSessionContext;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
public final class SSLSessionImpl implements SSLSession, Cloneable {
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java b/crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
index 93496cf..dc971ac 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketFactoryImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.net.InetAddress;
@@ -23,7 +23,7 @@
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import javax.net.ssl.SSLSocketFactory;
-import libcore.util.EmptyArray;
+import org.conscrypt.util.EmptyArray;
/**
* Implementation of SSLSocketFactory.
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java b/crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
index 3e72aeb..138a143 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketImpl.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java b/crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
index 8016579..36c5c03 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketInputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketInputStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
@@ -131,7 +131,7 @@
// to this input stream.
// It 'adapts' the InputStream interface to Appendable, which is used for
// transmission of income data from the record protocol to its clients.
- private class Adapter implements org.apache.harmony.xnet.provider.jsse.Appendable {
+ private class Adapter implements org.conscrypt.Appendable {
/**
* Appends the data to the stream.
* This method could be implemented in the outer class
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java b/crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
similarity index 96%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
index 2666eee..e3afed7 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketOutputStream.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketOutputStream.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.OutputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java b/crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java
rename to crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
index a393e24..2110aea 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLSocketWrapper.java
+++ b/crypto/src/main/java/org/conscrypt/SSLSocketWrapper.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.FileDescriptor;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java b/crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
rename to crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
index c040653..4c8a885 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLStreamedInput.java
+++ b/crypto/src/main/java/org/conscrypt/SSLStreamedInput.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.io.InputStream;
@@ -42,7 +42,7 @@
* @return the value read from the underlying stream.
* @throws IOException if the data could not be read from
* the underlying stream
- * @throws org.apache.harmony.xnet.provider.jsse.EndOfSourceException if the end of the underlying
+ * @throws org.conscrypt.EndOfSourceException if the end of the underlying
* stream has been reached.
*/
@Override
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java b/crypto/src/main/java/org/conscrypt/SSLv3Constants.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
rename to crypto/src/main/java/org/conscrypt/SSLv3Constants.java
index 43dc178..ea6482f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/SSLv3Constants.java
+++ b/crypto/src/main/java/org/conscrypt/SSLv3Constants.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
/**
*
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java b/crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
rename to crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
index 29cb9cd..2e55c0d 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHandshakeImpl.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHandshakeImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java b/crypto/src/main/java/org/conscrypt/ServerHello.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
rename to crypto/src/main/java/org/conscrypt/ServerHello.java
index 00a25f8..3cc3b46 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHello.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHello.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.SecureRandom;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java b/crypto/src/main/java/org/conscrypt/ServerHelloDone.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
rename to crypto/src/main/java/org/conscrypt/ServerHelloDone.java
index fd78b1f..3e40f9a 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerHelloDone.java
+++ b/crypto/src/main/java/org/conscrypt/ServerHelloDone.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java b/crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
rename to crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
index 7ccaf7cd3..d949850 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerKeyExchange.java
+++ b/crypto/src/main/java/org/conscrypt/ServerKeyExchange.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.math.BigInteger;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java b/crypto/src/main/java/org/conscrypt/ServerSessionContext.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
rename to crypto/src/main/java/org/conscrypt/ServerSessionContext.java
index f5716c1..8bd8b0f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/ServerSessionContext.java
+++ b/crypto/src/main/java/org/conscrypt/ServerSessionContext.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import javax.net.ssl.SSLSession;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java b/crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
similarity index 97%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
rename to crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
index 159e362..150d018 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerFactoryImpl.java
+++ b/crypto/src/main/java/org/conscrypt/TrustManagerFactoryImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java b/crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
similarity index 99%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
rename to crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
index a5a1978..ef366d2 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImpl.java
+++ b/crypto/src/main/java/org/conscrypt/TrustManagerImpl.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
index 0b1f098..b322cd1 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateIndex.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateIndex.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.PublicKey;
import java.security.cert.CertPathValidatorException;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
index 62a6647..c2d5c33 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateKeyStoreSpi.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateKeyStoreSpi.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.InputStream;
import java.io.OutputStream;
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
similarity index 85%
rename from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java
rename to crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
index e7b1a7c..1356776 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStore.java
+++ b/crypto/src/main/java/org/conscrypt/TrustedCertificateStore.java
@@ -14,13 +14,8 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
-import org.apache.harmony.security.x501.Name;
-import org.apache.harmony.security.x509.AuthorityKeyIdentifier;
-import org.apache.harmony.security.x509.GeneralName;
-import org.apache.harmony.security.x509.GeneralNames;
-import org.apache.harmony.security.x509.SubjectKeyIdentifier;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
@@ -28,20 +23,17 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.math.BigInteger;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
import libcore.io.IoUtils;
-import libcore.util.Objects;
/**
* A source for trusted root certificate authority (CA) certificates
@@ -380,107 +372,60 @@
return null;
}
- private static AuthorityKeyIdentifier getAuthorityKeyIdentifier(X509Certificate cert) {
- final byte[] akidBytes = cert.getExtensionValue("2.5.29.35");
- if (akidBytes == null) {
+ private static boolean isSelfIssuedCertificate(OpenSSLX509Certificate cert) {
+ final long ctx = cert.getContext();
+ return NativeCrypto.X509_check_issued(ctx, ctx) == 0;
+ }
+
+ /**
+ * Converts the {@code cert} to the internal OpenSSL X.509 format so we can
+ * run {@link NativeCrypto} methods on it.
+ */
+ private static OpenSSLX509Certificate convertToOpenSSLIfNeeded(X509Certificate cert)
+ throws CertificateException {
+ if (cert == null) {
return null;
}
+ if (cert instanceof OpenSSLX509Certificate) {
+ return (OpenSSLX509Certificate) cert;
+ }
+
try {
- return AuthorityKeyIdentifier.decode(akidBytes);
- } catch (IOException e) {
- return null;
+ return OpenSSLX509Certificate.fromX509Der(cert.getEncoded());
+ } catch (Exception e) {
+ throw new CertificateException(e);
}
}
- private static SubjectKeyIdentifier getSubjectKeyIdentifier(X509Certificate cert) {
- final byte[] skidBytes = cert.getExtensionValue("2.5.29.14");
- if (skidBytes == null) {
- return null;
- }
-
- try {
- return SubjectKeyIdentifier.decode(skidBytes);
- } catch (IOException e) {
- return null;
- }
- }
-
- private static boolean isSelfSignedCertificate(X509Certificate cert) {
- if (!Objects.equal(cert.getSubjectX500Principal(), cert.getIssuerX500Principal())) {
- return false;
- }
-
- final AuthorityKeyIdentifier akid = getAuthorityKeyIdentifier(cert);
- if (akid != null) {
- final byte[] akidKeyId = akid.getKeyIdentifier();
- if (akidKeyId != null) {
- final SubjectKeyIdentifier skid = getSubjectKeyIdentifier(cert);
- if (!Arrays.equals(akidKeyId, skid.getKeyIdentifier())) {
- return false;
- }
- }
-
- final BigInteger akidSerial = akid.getAuthorityCertSerialNumber();
- if (akidSerial != null && !akidSerial.equals(cert.getSerialNumber())) {
- return false;
- }
-
- final GeneralNames possibleIssuerNames = akid.getAuthorityCertIssuer();
- if (possibleIssuerNames != null) {
- GeneralName issuerName = null;
-
- /* Get the first Directory Name (DN) to match how OpenSSL works. */
- for (GeneralName possibleName : possibleIssuerNames.getNames()) {
- if (possibleName.getTag() == GeneralName.DIR_NAME) {
- issuerName = possibleName;
- break;
- }
- }
-
- if (issuerName != null) {
- final String issuerCanonical = ((Name) issuerName.getName())
- .getName(X500Principal.CANONICAL);
-
- try {
- final String subjectCanonical = new Name(cert.getSubjectX500Principal()
- .getEncoded()).getName(X500Principal.CANONICAL);
- if (!issuerCanonical.equals(subjectCanonical)) {
- return false;
- }
- } catch (IOException ignored) {
- }
- }
- }
- }
-
- return true;
- }
-
/**
* Attempt to build a certificate chain from the supplied {@code leaf}
* argument through the chain of issuers as high up as known. If the chain
* can't be completed, the most complete chain available will be returned.
* This means that a list with only the {@code leaf} certificate is returned
* if no issuer certificates could be found.
+ *
+ * @throws CertificateException if there was a problem parsing the
+ * certificates
*/
- public List<X509Certificate> getCertificateChain(X509Certificate leaf) {
- final List<X509Certificate> chain = new ArrayList<X509Certificate>();
- chain.add(leaf);
+ public List<X509Certificate> getCertificateChain(X509Certificate leaf)
+ throws CertificateException {
+ final List<OpenSSLX509Certificate> chain = new ArrayList<OpenSSLX509Certificate>();
+ chain.add(convertToOpenSSLIfNeeded(leaf));
for (int i = 0; true; i++) {
- X509Certificate cert = chain.get(i);
- if (isSelfSignedCertificate(cert)) {
+ OpenSSLX509Certificate cert = chain.get(i);
+ if (isSelfIssuedCertificate(cert)) {
break;
}
- X509Certificate issuer = findIssuer(cert);
+ OpenSSLX509Certificate issuer = convertToOpenSSLIfNeeded(findIssuer(cert));
if (issuer == null) {
break;
}
chain.add(issuer);
}
- return chain;
+ return new ArrayList<X509Certificate>(chain);
}
// like java.security.cert.CertSelector but with X509Certificate and without cloning
diff --git a/crypto/src/main/java/org/conscrypt/X509PublicKey.java b/crypto/src/main/java/org/conscrypt/X509PublicKey.java
new file mode 100644
index 0000000..8d09fc2
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/X509PublicKey.java
@@ -0,0 +1,86 @@
+/*
+ * 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 java.security.PublicKey;
+import java.util.Arrays;
+
+/**
+ * A simple but useless key class that holds X.509 public key information when
+ * the appropriate KeyFactory for the key algorithm is not available.
+ */
+public class X509PublicKey implements PublicKey {
+ private static final long serialVersionUID = -8610156854731664298L;
+
+ private final String algorithm;
+
+ private final byte[] encoded;
+
+ public X509PublicKey(String algorithm, byte[] encoded) {
+ this.algorithm = algorithm;
+ this.encoded = encoded;
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return algorithm;
+ }
+
+ @Override
+ public String getFormat() {
+ return "X.509";
+ }
+
+ @Override
+ public byte[] getEncoded() {
+ return encoded;
+ }
+
+ @Override
+ public String toString() {
+ return "X509PublicKey [algorithm=" + algorithm + ", encoded=" + Arrays.toString(encoded)
+ + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((algorithm == null) ? 0 : algorithm.hashCode());
+ result = prime * result + Arrays.hashCode(encoded);
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ X509PublicKey other = (X509PublicKey) obj;
+ if (algorithm == null) {
+ if (other.algorithm != null)
+ return false;
+ } else if (!algorithm.equals(other.algorithm))
+ return false;
+ if (!Arrays.equals(encoded, other.encoded))
+ return false;
+ return true;
+ }
+}
diff --git a/crypto/src/main/java/org/conscrypt/util/EmptyArray.java b/crypto/src/main/java/org/conscrypt/util/EmptyArray.java
new file mode 100644
index 0000000..e474562
--- /dev/null
+++ b/crypto/src/main/java/org/conscrypt/util/EmptyArray.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+// Copied from libcore.util.EmptyArray
+
+package org.conscrypt.util;
+
+public final class EmptyArray {
+ private EmptyArray() {}
+
+ public static final boolean[] BOOLEAN = new boolean[0];
+ public static final byte[] BYTE = new byte[0];
+ public static final char[] CHAR = new char[0];
+ public static final double[] DOUBLE = new double[0];
+ public static final int[] INT = new int[0];
+
+ public static final Class<?>[] CLASS = new Class[0];
+ public static final Object[] OBJECT = new Object[0];
+ 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];
+}
\ No newline at end of file
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
similarity index 94%
rename from luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
rename to crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
index 6df0aa8..8a59fdc 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/crypto/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -15,9 +15,16 @@
*/
/**
- * Native glue for Java class org.apache.harmony.xnet.provider.jsse.NativeCrypto
+ * Native glue for Java class org.conscrypt.NativeCrypto
*/
+#define TO_STRING1(x) #x
+#define TO_STRING(x) TO_STRING1(x)
+#ifndef JNI_JARJAR_PREFIX
+#define CONSCRYPT_UNBUNDLED
+#define JNI_JARJAR_PREFIX
+#endif
+
#define LOG_TAG "NativeCrypto"
#include <algorithm>
@@ -44,7 +51,6 @@
#include "JniConstants.h"
#include "JniException.h"
#include "NetFd.h"
-#include "NetworkUtilities.h"
#include "ScopedLocalRef.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
@@ -53,6 +59,21 @@
#undef WITH_JNI_TRACE
#undef WITH_JNI_TRACE_DATA
+/*
+ * How to use this for debugging with Wireshark:
+ *
+ * 1. Pull lines from logcat to a file that looks like (without quotes):
+ * "RSA Session-ID:... Master-Key:..." <CR>
+ * "RSA Session-ID:... Master-Key:..." <CR>
+ * <etc>
+ * 2. Start Wireshark
+ * 3. Go to Edit -> Preferences -> SSL -> (Pre-)Master-Key log and fill in
+ * the file you put the lines in above.
+ * 4. Follow the stream that corresponds to the desired "Session-ID" in
+ * the Server Hello.
+ */
+#undef WITH_JNI_TRACE_KEYS
+
#ifdef WITH_JNI_TRACE
#define JNI_TRACE(...) \
((void)ALOG(LOG_INFO, LOG_TAG "-jni", __VA_ARGS__)); \
@@ -70,6 +91,15 @@
static JavaVM* gJavaVM;
static jclass openSslOutputStreamClass;
+static jclass byteArrayClass;
+static jclass calendarClass;
+static jclass objectClass;
+static jclass objectArrayClass;
+static jclass integerClass;
+static jclass inputStreamClass;
+static jclass outputStreamClass;
+static jclass stringClass;
+
static jmethodID calendar_setMethod;
static jmethodID inputStream_readMethod;
static jmethodID integer_valueOfMethod;
@@ -317,6 +347,13 @@
}
/**
+ * Throws a OutOfMemoryError with the given string as a message.
+ */
+static void jniThrowOutOfMemory(JNIEnv* env, const char* message) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", message);
+}
+
+/**
* Throws a BadPaddingException with the given string as a message.
*/
static void throwBadPaddingException(JNIEnv* env, const char* message) {
@@ -1040,6 +1077,25 @@
};
/**
+ * Copied from libnativehelper NetworkUtilites.cpp
+ */
+static bool setBlocking(int fd, bool blocking) {
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1) {
+ return false;
+ }
+
+ if (!blocking) {
+ flags |= O_NONBLOCK;
+ } else {
+ flags &= ~O_NONBLOCK;
+ }
+
+ int rc = fcntl(fd, F_SETFL, flags);
+ return (rc != -1);
+}
+
+/**
* OpenSSL locking support. Taken from the O'Reilly book by Viega et al., but I
* suppose there are not many other ways to do this on a Linux system (modulo
* isomorphism).
@@ -1582,7 +1638,7 @@
Unique_BIO buffer(BIO_new(BIO_s_mem()));
if (buffer.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+ jniThrowOutOfMemory(env, "Unable to allocate BIO");
return NULL;
}
@@ -1612,7 +1668,7 @@
Unique_BIO buffer(BIO_new(BIO_s_mem()));
if (buffer.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+ jniThrowOutOfMemory(env, "Unable to allocate BIO");
return NULL;
}
@@ -1760,7 +1816,7 @@
Unique_RSA rsa(RSA_new());
if (rsa.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate RSA key");
+ jniThrowOutOfMemory(env, "Unable to allocate RSA key");
return 0;
}
@@ -1875,7 +1931,7 @@
return 0;
}
- jobjectArray joa = env->NewObjectArray(2, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -1913,7 +1969,7 @@
return 0;
}
- jobjectArray joa = env->NewObjectArray(8, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(8, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -2008,7 +2064,7 @@
Unique_DSA dsa(DSA_new());
if (dsa.get() == NULL) {
JNI_TRACE("DSA_generate_key failed");
- jniThrowOutOfMemoryError(env, "Unable to allocate DSA key");
+ jniThrowOutOfMemory(env, "Unable to allocate DSA key");
freeOpenSslErrorState();
return 0;
}
@@ -2075,7 +2131,7 @@
return 0;
}
- jobjectArray joa = env->NewObjectArray(5, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(5, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -2309,7 +2365,7 @@
return NULL;
}
- jobjectArray joa = env->NewObjectArray(3, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(3, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -2344,7 +2400,7 @@
Unique_BIGNUM order(BN_new());
if (order.get() == NULL) {
JNI_TRACE("EC_GROUP_get_order(%p) => can't create BN", group);
- jniThrowOutOfMemoryError(env, "BN_new");
+ jniThrowOutOfMemory(env, "BN_new");
return NULL;
}
@@ -2387,7 +2443,7 @@
Unique_BIGNUM cofactor(BN_new());
if (cofactor.get() == NULL) {
JNI_TRACE("EC_GROUP_get_cofactor(%p) => can't create BN", group);
- jniThrowOutOfMemoryError(env, "BN_new");
+ jniThrowOutOfMemory(env, "BN_new");
return NULL;
}
@@ -2503,7 +2559,7 @@
Unique_EC_POINT dup(EC_POINT_dup(generator, group));
if (dup.get() == NULL) {
JNI_TRACE("EC_GROUP_get_generator(%p) => oom error", group);
- jniThrowOutOfMemoryError(env, "unable to dupe generator");
+ jniThrowOutOfMemory(env, "unable to dupe generator");
return 0;
}
@@ -2524,7 +2580,7 @@
EC_POINT* point = EC_POINT_new(group);
if (point == NULL) {
- jniThrowOutOfMemoryError(env, "Unable create an EC_POINT");
+ jniThrowOutOfMemory(env, "Unable create an EC_POINT");
return 0;
}
@@ -2641,7 +2697,7 @@
return NULL;
}
- jobjectArray joa = env->NewObjectArray(2, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(2, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -2670,7 +2726,7 @@
Unique_EC_KEY eckey(EC_KEY_new());
if (eckey.get() == NULL) {
JNI_TRACE("EC_KEY_generate_key(%p) => EC_KEY_new() oom", group);
- jniThrowOutOfMemoryError(env, "Unable to create an EC_KEY");
+ jniThrowOutOfMemory(env, "Unable to create an EC_KEY");
return 0;
}
@@ -2830,7 +2886,7 @@
Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
if (ctx.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable create a EVP_MD_CTX");
+ jniThrowOutOfMemory(env, "Unable create a EVP_MD_CTX");
return 0;
}
@@ -2867,7 +2923,7 @@
EVP_MD_CTX* copy = EVP_MD_CTX_create();
if (copy == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate copy of EVP_MD_CTX");
+ jniThrowOutOfMemory(env, "Unable to allocate copy of EVP_MD_CTX");
return 0;
}
@@ -2928,7 +2984,7 @@
Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
if (ctx.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+ jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
return 0;
}
JNI_TRACE("NativeCrypto_EVP_DigestInit ctx=%p", ctx.get());
@@ -3148,7 +3204,7 @@
Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
if (ctx.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+ jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
return 0;
}
JNI_TRACE("NativeCrypto_EVP_SignInit ctx=%p", ctx.get());
@@ -3249,7 +3305,7 @@
Unique_EVP_MD_CTX ctx(EVP_MD_CTX_create());
if (ctx.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate EVP_MD_CTX");
+ jniThrowOutOfMemory(env, "Unable to allocate EVP_MD_CTX");
return 0;
}
JNI_TRACE("NativeCrypto_EVP_VerifyInit ctx=%p", ctx.get());
@@ -3514,7 +3570,7 @@
Unique_EVP_CIPHER_CTX ctx(EVP_CIPHER_CTX_new());
if (ctx.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate cipher context");
+ jniThrowOutOfMemory(env, "Unable to allocate cipher context");
JNI_TRACE("EVP_CipherInit_ex => context allocation error");
return 0;
}
@@ -3741,7 +3797,7 @@
UniquePtr<unsigned char[]> buffer(new unsigned char[outputSize]);
if (buffer.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate buffer for read");
+ jniThrowOutOfMemory(env, "Unable to allocate buffer for read");
return 0;
}
@@ -3783,7 +3839,7 @@
UniquePtr<unsigned char[]> buffer(new unsigned char[length]);
if (buffer.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate buffer for write");
+ jniThrowOutOfMemory(env, "Unable to allocate buffer for write");
return;
}
@@ -3815,7 +3871,7 @@
Unique_BIO buffer(BIO_new(BIO_s_mem()));
if (buffer.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate BIO");
+ jniThrowOutOfMemory(env, "Unable to allocate BIO");
JNI_TRACE("X509_NAME_to_jstring(%p) => threw error", name);
return NULL;
}
@@ -3939,8 +3995,7 @@
*/
const int origCount = count;
- ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count,
- JniConstants::objectArrayClass, NULL));
+ ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, objectArrayClass, NULL));
for (int i = 0, j = 0; i < origCount; i++, j++) {
GENERAL_NAME* gen = sk_GENERAL_NAME_value(gn_stack, i);
ScopedLocalRef<jobject> val(env, GENERAL_NAME_to_jobject(env, gen));
@@ -3960,10 +4015,9 @@
continue;
}
- ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, JniConstants::objectClass,
- NULL));
+ ScopedLocalRef<jobjectArray> item(env, env->NewObjectArray(2, objectClass, NULL));
- ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(JniConstants::integerClass,
+ ScopedLocalRef<jobject> type(env, env->CallStaticObjectMethod(integerClass,
integer_valueOfMethod, gen->type));
env->SetObjectArrayElement(item.get(), 0, type.get());
env->SetObjectArrayElement(item.get(), 1, val.get());
@@ -3979,8 +4033,8 @@
JNI_TRACE("get_X509_GENERAL_NAME_stack(%p, %d) shrunk from %d to %d", x509, type,
origCount, count);
- ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count,
- JniConstants::objectArrayClass, NULL));
+ ScopedLocalRef<jobjectArray> joa_copy(env, env->NewObjectArray(count, objectArrayClass,
+ NULL));
for (int i = 0; i < count; i++) {
ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(joa.get(), i));
@@ -4125,6 +4179,16 @@
return x509->ex_flags;
}
+static jboolean NativeCrypto_X509_check_issued(JNIEnv*, jclass, jlong x509Ref1, jlong x509Ref2) {
+ X509* x509_1 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref1));
+ X509* x509_2 = reinterpret_cast<X509*>(static_cast<uintptr_t>(x509Ref2));
+ JNI_TRACE("X509_check_issued(%p, %p)", x509_1, x509_2);
+
+ int ret = X509_check_issued(x509_1, x509_2);
+ JNI_TRACE("X509_check_issued(%p, %p) => %d", x509_1, x509_2, ret);
+ return ret;
+}
+
static void get_X509_signature(X509 *x509, ASN1_BIT_STRING** signature) {
*signature = x509->signature;
}
@@ -5168,8 +5232,7 @@
}
size_t size = sk_ASN1_OBJECT_num(objArray.get());
- ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size,
- JniConstants::stringClass, NULL));
+ ScopedLocalRef<jobjectArray> exKeyUsage(env, env->NewObjectArray(size, stringClass, NULL));
if (exKeyUsage.get() == NULL) {
return NULL;
}
@@ -5243,7 +5306,7 @@
JNI_TRACE("get_X509Type_ext_oids(%p, %d) has %d entries", x509, critical, count);
- ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, JniConstants::stringClass, NULL));
+ ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, stringClass, NULL));
if (joa.get() == NULL) {
JNI_TRACE("get_X509Type_ext_oids(%p, %d) => fail to allocate result array", x509, critical);
return NULL;
@@ -5357,7 +5420,7 @@
return NULL;
}
- jobjectArray joa = env->NewObjectArray(count, JniConstants::byteArrayClass, NULL);
+ jobjectArray joa = env->NewObjectArray(count, byteArrayClass, NULL);
if (joa == NULL) {
return NULL;
}
@@ -5389,8 +5452,7 @@
return NULL;
}
- ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, JniConstants::byteArrayClass,
- NULL));
+ ScopedLocalRef<jobjectArray> joa(env, env->NewObjectArray(count, byteArrayClass, NULL));
if (joa.get() == NULL) {
return NULL;
}
@@ -5496,6 +5558,9 @@
jbyteArray npnProtocolsArray;
jbyte* npnProtocolsData;
size_t npnProtocolsLength;
+ jbyteArray alpnProtocolsArray;
+ jbyte* alpnProtocolsData;
+ size_t alpnProtocolsLength;
Unique_RSA ephemeralRsa;
Unique_EC_KEY ephemeralEc;
@@ -5540,6 +5605,9 @@
npnProtocolsArray(NULL),
npnProtocolsData(NULL),
npnProtocolsLength(-1),
+ alpnProtocolsArray(NULL),
+ alpnProtocolsData(NULL),
+ alpnProtocolsLength(-1),
ephemeralRsa(NULL),
ephemeralEc(NULL) {
fdsEmergency[0] = -1;
@@ -5558,8 +5626,12 @@
* @param npnProtocols NPN protocols so that they may be advertised (by the
* server) or selected (by the client). Has no effect
* unless NPN is enabled.
+ * @param alpnProtocols ALPN protocols so that they may be advertised (by the
+ * server) or selected (by the client). Passing non-NULL
+ * enables ALPN.
*/
- bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols) {
+ bool setCallbackState(JNIEnv* e, jobject shc, jobject fd, jbyteArray npnProtocols,
+ jbyteArray alpnProtocols) {
NetFd netFd(e, fd);
if (netFd.isClosed()) {
return false;
@@ -5575,6 +5647,14 @@
return false;
}
}
+ if (alpnProtocols != NULL) {
+ alpnProtocolsArray = alpnProtocols;
+ alpnProtocolsLength = e->GetArrayLength(alpnProtocols);
+ alpnProtocolsData = e->GetByteArrayElements(alpnProtocols, NULL);
+ if (alpnProtocolsData == NULL) {
+ return false;
+ }
+ }
return true;
}
@@ -5587,6 +5667,12 @@
npnProtocolsData = NULL;
npnProtocolsLength = -1;
}
+ if (alpnProtocolsArray != NULL) {
+ env->ReleaseByteArrayElements(alpnProtocolsArray, alpnProtocolsData, JNI_ABORT);
+ alpnProtocolsArray = NULL;
+ alpnProtocolsData = NULL;
+ alpnProtocolsLength = -1;
+ }
env = NULL;
}
@@ -5883,6 +5969,9 @@
*x509Out = certificate;
*pkeyOut = privatekey;
result = 1;
+ } else {
+ // Some error conditions return NULL, so make sure it doesn't linger.
+ freeOpenSslErrorState();
}
JNI_TRACE("ssl=%p client_cert_cb => *x509=%p *pkey=%p %d", ssl, *x509Out, *pkeyOut, result);
return result;
@@ -6178,18 +6267,19 @@
return javaBytes;
}
-static void NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(
- JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef)
+static void NativeCrypto_SSL_set1_tls_channel_id(JNIEnv* env, jclass,
+ jlong ssl_address, jlong pkeyRef)
{
SSL* ssl = to_SSL(env, ssl_address, true);
EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id privatekey=%p",
- ssl, pkey);
+ JNI_TRACE("ssl=%p SSL_set1_tls_channel_id privatekey=%p", ssl, pkey);
if (ssl == NULL) {
return;
}
if (pkey == NULL) {
+ jniThrowNullPointerException(env, "pkey == null");
+ JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => pkey == null", ssl);
return;
}
@@ -6204,86 +6294,28 @@
throwSSLExceptionWithSslErrors(
env, ssl, SSL_ERROR_NONE, "Error setting private key for Channel ID");
SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id => error", ssl);
+ JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => error", ssl);
return;
}
- // SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
- // but we have an external reference from the caller such as an
- // OpenSSLKey, so we manually increment the reference count here.
+ // SSL_set1_tls_channel_id expects to take ownership of the EVP_PKEY, but
+ // we have an external reference from the caller such as an OpenSSLKey,
+ // so we manually increment the reference count here.
CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_OpenSSL_PrivateKey_for_tls_channel_id => ok", ssl);
+ JNI_TRACE("ssl=%p SSL_set1_tls_channel_id => ok", ssl);
}
-static void NativeCrypto_SSL_use_PKCS8_PrivateKey_for_tls_channel_id(
- JNIEnv* env, jclass, jlong ssl_address, jbyteArray privatekey)
-{
- SSL* ssl = to_SSL(env, ssl_address, true);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id privatekey=%p", ssl,
- privatekey);
- if (ssl == NULL) {
- return;
- }
-
- ScopedByteArrayRO buf(env, privatekey);
- if (buf.get() == NULL) {
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => threw exception",
- ssl);
- return;
- }
- const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
- Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size()));
- if (pkcs8.get() == NULL) {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
- "Error parsing private key from DER to PKCS8");
- SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl);
- return;
- }
-
- Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get()));
- if (privatekeyevp.get() == NULL) {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
- "Error creating private key from PKCS8");
- SSL_clear(ssl);
- JNI_TRACE(
- "ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => error from PKCS8 to key",
- ssl);
- return;
- }
-
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id EVP_PKEY_type=%d",
- ssl, EVP_PKEY_type(privatekeyevp.get()->type));
-
- // SSL_set1_tls_channel_id requires ssl->server to be set to 0.
- // Unfortunately, the default value is 1 and it's only changed to 0 just
- // before the handshake starts (see NativeCrypto_SSL_do_handshake).
- ssl->server = 0;
- long ret = SSL_set1_tls_channel_id(ssl, privatekeyevp.get());
- if (ret == 1L) {
- OWNERSHIP_TRANSFERRED(privatekeyevp);
- } else {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
- SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => error", ssl);
- return;
- }
-
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey_for_tls_channel_id => ok", ssl);
-}
-
-static void NativeCrypto_SSL_use_OpenSSL_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
+static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass, jlong ssl_address, jlong pkeyRef) {
SSL* ssl = to_SSL(env, ssl_address, true);
EVP_PKEY* pkey = reinterpret_cast<EVP_PKEY*>(pkeyRef);
- JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey privatekey=%p", ssl, pkey);
+ JNI_TRACE("ssl=%p SSL_use_PrivateKey privatekey=%p", ssl, pkey);
if (ssl == NULL) {
return;
}
if (pkey == NULL) {
+ jniThrowNullPointerException(env, "pkey == null");
+ JNI_TRACE("ssl=%p SSL_use_PrivateKey => pkey == null", ssl);
return;
}
@@ -6292,7 +6324,7 @@
ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
SSL_clear(ssl);
- JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey => error", ssl);
+ JNI_TRACE("ssl=%p SSL_use_PrivateKey => error", ssl);
return;
}
// SSL_use_PrivateKey expects to take ownership of the EVP_PKEY,
@@ -6300,58 +6332,7 @@
// OpenSSLKey, so we manually increment the reference count here.
CRYPTO_add(&pkey->references,+1,CRYPTO_LOCK_EVP_PKEY);
- JNI_TRACE("ssl=%p SSL_use_OpenSSL_PrivateKey => ok", ssl);
-}
-
-static void NativeCrypto_SSL_use_PrivateKey(JNIEnv* env, jclass,
- jlong ssl_address, jbyteArray privatekey)
-{
- SSL* ssl = to_SSL(env, ssl_address, true);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey privatekey=%p", ssl, privatekey);
- if (ssl == NULL) {
- return;
- }
-
- ScopedByteArrayRO buf(env, privatekey);
- if (buf.get() == NULL) {
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => threw exception", ssl);
- return;
- }
- const unsigned char* tmp = reinterpret_cast<const unsigned char*>(buf.get());
- Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &tmp, buf.size()));
- if (pkcs8.get() == NULL) {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
- "Error parsing private key from DER to PKCS8");
- SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from DER to PKCS8", ssl);
- return;
- }
-
- Unique_EVP_PKEY privatekeyevp(EVP_PKCS82PKEY(pkcs8.get()));
- if (privatekeyevp.get() == NULL) {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE,
- "Error creating private key from PKCS8");
- SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error from PKCS8 to key", ssl);
- return;
- }
-
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey EVP_PKEY_type=%d",
- ssl, EVP_PKEY_type(privatekeyevp.get()->type));
- int ret = SSL_use_PrivateKey(ssl, privatekeyevp.get());
- if (ret == 1) {
- OWNERSHIP_TRANSFERRED(privatekeyevp);
- } else {
- ALOGE("%s", ERR_error_string(ERR_peek_error(), NULL));
- throwSSLExceptionWithSslErrors(env, ssl, SSL_ERROR_NONE, "Error setting private key");
- SSL_clear(ssl);
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => error", ssl);
- return;
- }
-
- JNI_TRACE("ssl=%p NativeCrypto_SSL_use_PrivateKey => ok", ssl);
+ JNI_TRACE("ssl=%p SSL_use_PrivateKey => ok", ssl);
}
static void NativeCrypto_SSL_use_certificate(JNIEnv* env, jclass,
@@ -6416,13 +6397,13 @@
Unique_sk_X509 chain(sk_X509_new_null());
if (chain.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
+ jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => chain allocation error", ssl);
return;
}
for (int i = 1; i < length; i++) {
if (!sk_X509_push(chain.get(), certificatesX509.release(i))) {
- jniThrowOutOfMemoryError(env, "Unable to push certificate");
+ jniThrowOutOfMemory(env, "Unable to push certificate");
JNI_TRACE("ssl=%p NativeCrypto_SSL_use_certificate => certificate push error", ssl);
return;
}
@@ -6481,7 +6462,7 @@
Unique_sk_X509_NAME principalsStack(sk_X509_NAME_new_null());
if (principalsStack.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate principal stack");
+ jniThrowOutOfMemory(env, "Unable to allocate principal stack");
JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => stack allocation error", ssl);
return;
}
@@ -6512,7 +6493,7 @@
}
if (!sk_X509_NAME_push(principalsStack.get(), principalX509Name.release())) {
- jniThrowOutOfMemoryError(env, "Unable to push principal");
+ jniThrowOutOfMemory(env, "Unable to push principal");
JNI_TRACE("ssl=%p NativeCrypto_SSL_set_client_CA_list => principal push error", ssl);
return;
}
@@ -6652,7 +6633,7 @@
if ((strcmp(c.c_str(), cipher->name) == 0)
&& (strcmp(SSL_CIPHER_get_version(cipher), "SSLv2"))) {
if (!sk_SSL_CIPHER_push(cipherstack.get(), cipher)) {
- jniThrowOutOfMemoryError(env, "Unable to push cipher");
+ jniThrowOutOfMemory(env, "Unable to push cipher");
JNI_TRACE("ssl=%p NativeCrypto_SSL_set_cipher_lists => cipher push error", ssl);
return;
}
@@ -6771,36 +6752,69 @@
}
/**
- * Callback for the client to select a protocol.
+ * A common selection path for both NPN and ALPN since they're essentially the
+ * same protocol. The list of protocols in "primary" is considered the order
+ * which should take precedence.
*/
-static int next_proto_select_callback(SSL* ssl, unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen, void *)
+static int proto_select(SSL* ssl __attribute__ ((unused)),
+ unsigned char **out, unsigned char *outLength,
+ const unsigned char *primary, const unsigned int primaryLength,
+ const unsigned char *secondary, const unsigned int secondaryLength) {
+ if (primary != NULL) {
+ JNI_TRACE("primary=%p, length=%d", primary, primaryLength);
+
+ int status = SSL_select_next_proto(out, outLength, primary, primaryLength, secondary,
+ secondaryLength);
+ switch (status) {
+ case OPENSSL_NPN_NEGOTIATED:
+ JNI_TRACE("ssl=%p proto_select NPN/ALPN negotiated", ssl);
+ break;
+ case OPENSSL_NPN_UNSUPPORTED:
+ JNI_TRACE("ssl=%p proto_select NPN/ALPN unsupported", ssl);
+ break;
+ case OPENSSL_NPN_NO_OVERLAP:
+ JNI_TRACE("ssl=%p proto_select NPN/ALPN no overlap", ssl);
+ break;
+ }
+ } else {
+ JNI_TRACE("protocols=NULL");
+ }
+ return SSL_TLSEXT_ERR_OK;
+}
+
+/**
+ * Callback for the server to select an ALPN protocol.
+ */
+static int alpn_select_callback(SSL* ssl, const unsigned char **out, unsigned char *outlen,
+ const unsigned char *in, unsigned int inlen, void *) {
+ JNI_TRACE("ssl=%p alpn_select_callback", ssl);
+
+ AppData* appData = toAppData(ssl);
+ JNI_TRACE("AppData=%p", appData);
+
+ return proto_select(ssl, const_cast<unsigned char **>(out), outlen,
+ reinterpret_cast<unsigned char*>(appData->alpnProtocolsData),
+ appData->alpnProtocolsLength, in, inlen);
+}
+
+/**
+ * Callback for the client to select an NPN protocol.
+ */
+static int next_proto_select_callback(SSL* ssl, unsigned char** out, unsigned char* outlen,
+ const unsigned char* in, unsigned int inlen, void*)
{
JNI_TRACE("ssl=%p next_proto_select_callback", ssl);
+ AppData* appData = toAppData(ssl);
+ JNI_TRACE("AppData=%p", appData);
+
// Enable False Start on the client if the server understands NPN
// http://www.imperialviolet.org/2012/04/11/falsestart.html
SSL_set_mode(ssl, SSL_MODE_HANDSHAKE_CUTTHROUGH);
- AppData* appData = toAppData(ssl);
- JNI_TRACE("AppData=%p", appData);
- unsigned char* npnProtocols = reinterpret_cast<unsigned char*>(appData->npnProtocolsData);
- size_t npnProtocolsLength = appData->npnProtocolsLength;
- JNI_TRACE("npn_protocols=%p, length=%d", npnProtocols, npnProtocolsLength);
-
- int status = SSL_select_next_proto(out, outlen, in, inlen, npnProtocols, npnProtocolsLength);
- switch (status) {
- case OPENSSL_NPN_NEGOTIATED:
- JNI_TRACE("ssl=%p next_proto_select_callback NPN negotiated", ssl);
- break;
- case OPENSSL_NPN_UNSUPPORTED:
- JNI_TRACE("ssl=%p next_proto_select_callback NPN unsupported", ssl);
- break;
- case OPENSSL_NPN_NO_OVERLAP:
- JNI_TRACE("ssl=%p next_proto_select_callback NPN no overlap", ssl);
- break;
- }
- return SSL_TLSEXT_ERR_OK;
+ return proto_select(ssl, out, outlen, in, inlen,
+ reinterpret_cast<unsigned char*>(appData->npnProtocolsData),
+ appData->npnProtocolsLength);
}
/**
@@ -6860,13 +6874,120 @@
return result;
}
+static int NativeCrypto_SSL_CTX_set_alpn_protos(JNIEnv* env, jclass, jlong ssl_ctx_address,
+ jbyteArray protos) {
+ SSL_CTX* ssl_ctx = to_SSL_CTX(env, ssl_ctx_address, true);
+ if (ssl_ctx == NULL) {
+ return 0;
+ }
+
+ JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p", ssl_ctx, protos);
+
+ if (protos == NULL) {
+ JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=NULL", ssl_ctx);
+ return 1;
+ }
+
+ ScopedByteArrayRO protosBytes(env, protos);
+ if (protosBytes.get() == NULL) {
+ JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => protosBytes == NULL", ssl_ctx,
+ protos);
+ return 0;
+ }
+
+ const unsigned char *tmp = reinterpret_cast<const unsigned char*>(protosBytes.get());
+ int ret = SSL_CTX_set_alpn_protos(ssl_ctx, tmp, protosBytes.size());
+ JNI_TRACE("ssl_ctx=%p SSL_CTX_set_alpn_protos protos=%p => ret=%d", ssl_ctx, protos, ret);
+ return ret;
+}
+
+static jbyteArray NativeCrypto_SSL_get0_alpn_selected(JNIEnv* env, jclass,
+ jlong ssl_address)
+{
+ SSL* ssl = to_SSL(env, ssl_address, true);
+ JNI_TRACE("ssl=%p SSL_get0_alpn_selected", ssl);
+ if (ssl == NULL) {
+ return NULL;
+ }
+ const jbyte* npn;
+ unsigned npnLength;
+ SSL_get0_alpn_selected(ssl, reinterpret_cast<const unsigned char**>(&npn), &npnLength);
+ if (npnLength == 0) {
+ return NULL;
+ }
+ jbyteArray result = env->NewByteArray(npnLength);
+ if (result != NULL) {
+ env->SetByteArrayRegion(result, 0, npnLength, npn);
+ }
+ return result;
+}
+
+#ifdef WITH_JNI_TRACE_KEYS
+static inline char hex_char(unsigned char in)
+{
+ if (in < 10) {
+ return '0' + in;
+ } else if (in <= 0xF0) {
+ return 'A' + in - 10;
+ } else {
+ return '?';
+ }
+}
+
+static void hex_string(char **dest, unsigned char* input, int len)
+{
+ *dest = (char*) malloc(len * 2 + 1);
+ char *output = *dest;
+ for (int i = 0; i < len; i++) {
+ *output++ = hex_char(input[i] >> 4);
+ *output++ = hex_char(input[i] & 0xF);
+ }
+ *output = '\0';
+}
+
+static void debug_print_session_key(SSL_SESSION* session)
+{
+ char *session_id_str;
+ char *master_key_str;
+ const char *key_type;
+ char *keyline;
+
+ hex_string(&session_id_str, session->session_id, session->session_id_length);
+ hex_string(&master_key_str, session->master_key, session->master_key_length);
+
+ X509* peer = SSL_SESSION_get0_peer(session);
+ EVP_PKEY* pkey = X509_PUBKEY_get(peer->cert_info->key);
+ switch (EVP_PKEY_type(pkey->type)) {
+ case EVP_PKEY_RSA:
+ key_type = "RSA";
+ break;
+ case EVP_PKEY_DSA:
+ key_type = "DSA";
+ break;
+ case EVP_PKEY_EC:
+ key_type = "EC";
+ break;
+ default:
+ key_type = "Unknown";
+ break;
+ }
+
+ asprintf(&keyline, "%s Session-ID:%s Master-Key:%s\n", key_type, session_id_str,
+ master_key_str);
+ JNI_TRACE("ssl_session=%p %s", session, keyline);
+
+ free(session_id_str);
+ free(master_key_str);
+ free(keyline);
+}
+#endif /* WITH_JNI_TRACE_KEYS */
+
/**
* Perform SSL handshake
*/
-static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address,
- jobject fdObject, jobject shc, jint timeout_millis, jboolean client_mode,
- jbyteArray npnProtocols)
-{
+static jlong NativeCrypto_SSL_do_handshake(JNIEnv* env, jclass, jlong ssl_address, jobject fdObject,
+ jobject shc, jint timeout_millis, jboolean client_mode, jbyteArray npnProtocols,
+ jbyteArray alpnProtocols) {
SSL* ssl = to_SSL(env, ssl_address, true);
JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake fd=%p shc=%p timeout_millis=%d client_mode=%d npn=%p",
ssl, fdObject, shc, timeout_millis, client_mode, npnProtocols);
@@ -6932,13 +7053,16 @@
SSL_set_connect_state(ssl);
} else {
SSL_set_accept_state(ssl);
+ if (alpnProtocols != NULL) {
+ SSL_CTX_set_alpn_select_cb(SSL_get_SSL_CTX(ssl), alpn_select_callback, NULL);
+ }
}
ret = 0;
while (appData->aliveAndKicking) {
errno = 0;
- if (!appData->setCallbackState(env, shc, fdObject, npnProtocols)) {
+ if (!appData->setCallbackState(env, shc, fdObject, npnProtocols, alpnProtocols)) {
// SocketException thrown by NetFd.isClosed
SSL_clear(ssl);
JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake setCallbackState => 0", ssl);
@@ -7034,6 +7158,9 @@
}
SSL_SESSION* ssl_session = SSL_get1_session(ssl);
JNI_TRACE("ssl=%p NativeCrypto_SSL_do_handshake => ssl_session=%p", ssl, ssl_session);
+#ifdef WITH_JNI_TRACE_KEYS
+ debug_print_session_key(ssl_session);
+#endif
return (jlong) ssl_session;
}
@@ -7079,24 +7206,26 @@
X509* certificate = SSL_get_certificate(ssl);
if (certificate == NULL) {
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
+ // SSL_get_certificate can return NULL during an error as well.
+ freeOpenSslErrorState();
return NULL;
}
Unique_sk_X509 chain(sk_X509_new_null());
if (chain.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate local certificate chain");
+ jniThrowOutOfMemory(env, "Unable to allocate local certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => threw exception", ssl);
return NULL;
}
if (!sk_X509_push(chain.get(), certificate)) {
- jniThrowOutOfMemoryError(env, "Unable to push local 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))) {
- jniThrowOutOfMemoryError(env, "Unable to push local certificate chain");
+ jniThrowOutOfMemory(env, "Unable to push local certificate chain");
JNI_TRACE("ssl=%p NativeCrypto_SSL_get_certificate => NULL", ssl);
return NULL;
}
@@ -7125,12 +7254,12 @@
}
chain_copy.reset(sk_X509_dup(chain));
if (chain_copy.get() == NULL) {
- jniThrowOutOfMemoryError(env, "Unable to allocate peer certificate chain");
+ 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)) {
- jniThrowOutOfMemoryError(env, "Unable to push server's peer certificate");
+ 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;
}
@@ -7178,7 +7307,7 @@
unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
- if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+ if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
MUTEX_UNLOCK(appData->mutex);
return THROWN_EXCEPTION;
}
@@ -7199,7 +7328,7 @@
#ifdef WITH_JNI_TRACE_DATA
for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
- JNI_TRACE("ssl=%p sslRead data: %d:\n%*s", ssl, n, n, buf+i);
+ JNI_TRACE("ssl=%p sslRead data: %d:\n%.*s", ssl, n, n, buf+i);
}
#endif
@@ -7380,7 +7509,7 @@
unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
- if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+ if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
MUTEX_UNLOCK(appData->mutex);
return THROWN_EXCEPTION;
}
@@ -7403,7 +7532,7 @@
#ifdef WITH_JNI_TRACE_DATA
for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
- JNI_TRACE("ssl=%p sslWrite data: %d:\n%*s", ssl, n, n, buf+i);
+ JNI_TRACE("ssl=%p sslWrite data: %d:\n%.*s", ssl, n, n, buf+i);
}
#endif
@@ -7585,7 +7714,7 @@
AppData* appData = toAppData(ssl);
if (appData != NULL) {
- if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
+ if (!appData->setCallbackState(env, shc, fdObject, NULL, NULL)) {
// SocketException thrown by NetFd.isClosed
SSL_clear(ssl);
freeOpenSslErrorState();
@@ -7747,6 +7876,9 @@
static jbyteArray NativeCrypto_i2d_SSL_SESSION(JNIEnv* env, jclass, jlong ssl_session_address) {
SSL_SESSION* ssl_session = to_SSL_SESSION(env, ssl_session_address, true);
JNI_TRACE("ssl_session=%p NativeCrypto_i2d_SSL_SESSION", ssl_session);
+ if (ssl_session == NULL) {
+ return NULL;
+ }
return ASN1ToByteArray<SSL_SESSION, i2d_SSL_SESSION>(env, ssl_session);
}
@@ -7792,7 +7924,7 @@
}
#define FILE_DESCRIPTOR "Ljava/io/FileDescriptor;"
-#define SSL_CALLBACKS "Lorg/apache/harmony/xnet/provider/jsse/NativeCrypto$SSLHandshakeCallbacks;"
+#define SSL_CALLBACKS "L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto$SSLHandshakeCallbacks;"
static JNINativeMethod sNativeCryptoMethods[] = {
NATIVE_METHOD(NativeCrypto, clinit, "()V"),
NATIVE_METHOD(NativeCrypto, ENGINE_load_dynamic, "()V"),
@@ -7889,7 +8021,7 @@
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid, "(Ljava/lang/String;)I"),
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_longName, "(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(NativeCrypto, OBJ_txt2nid_oid, "(Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, "(Lorg/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream;)J"),
+ NATIVE_METHOD(NativeCrypto, create_BIO_InputStream, ("(L" TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream;)J")),
NATIVE_METHOD(NativeCrypto, create_BIO_OutputStream, "(Ljava/io/OutputStream;)J"),
NATIVE_METHOD(NativeCrypto, BIO_read, "(J[B)I"),
NATIVE_METHOD(NativeCrypto, BIO_write, "(J[BII)V"),
@@ -7943,6 +8075,7 @@
NATIVE_METHOD(NativeCrypto, get_X509_signature, "(J)[B"),
NATIVE_METHOD(NativeCrypto, get_X509_CRL_signature, "(J)[B"),
NATIVE_METHOD(NativeCrypto, get_X509_ex_flags, "(J)I"),
+ NATIVE_METHOD(NativeCrypto, X509_check_issued, "(JJ)I"),
NATIVE_METHOD(NativeCrypto, d2i_X509_CRL_bio, "(J)J"),
NATIVE_METHOD(NativeCrypto, PEM_read_bio_X509_CRL, "(J)J"),
NATIVE_METHOD(NativeCrypto, X509_CRL_get0_by_cert, "(JJ)J"),
@@ -7967,10 +8100,8 @@
NATIVE_METHOD(NativeCrypto, SSL_new, "(J)J"),
NATIVE_METHOD(NativeCrypto, SSL_enable_tls_channel_id, "(J)V"),
NATIVE_METHOD(NativeCrypto, SSL_get_tls_channel_id, "(J)[B"),
- NATIVE_METHOD(NativeCrypto, SSL_use_OpenSSL_PrivateKey_for_tls_channel_id, "(JJ)V"),
- NATIVE_METHOD(NativeCrypto, SSL_use_PKCS8_PrivateKey_for_tls_channel_id, "(J[B)V"),
- NATIVE_METHOD(NativeCrypto, SSL_use_OpenSSL_PrivateKey, "(JJ)V"),
- NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(J[B)V"),
+ NATIVE_METHOD(NativeCrypto, SSL_set1_tls_channel_id, "(JJ)V"),
+ NATIVE_METHOD(NativeCrypto, SSL_use_PrivateKey, "(JJ)V"),
NATIVE_METHOD(NativeCrypto, SSL_use_certificate, "(J[[B)V"),
NATIVE_METHOD(NativeCrypto, SSL_check_private_key, "(J)V"),
NATIVE_METHOD(NativeCrypto, SSL_set_client_CA_list, "(J[[B)V"),
@@ -7986,7 +8117,7 @@
NATIVE_METHOD(NativeCrypto, SSL_set_session_creation_enabled, "(JZ)V"),
NATIVE_METHOD(NativeCrypto, SSL_set_tlsext_host_name, "(JLjava/lang/String;)V"),
NATIVE_METHOD(NativeCrypto, SSL_get_servername, "(J)Ljava/lang/String;"),
- NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B)I"),
+ NATIVE_METHOD(NativeCrypto, SSL_do_handshake, "(J" FILE_DESCRIPTOR SSL_CALLBACKS "IZ[B[B)I"),
NATIVE_METHOD(NativeCrypto, SSL_renegotiate, "(J)V"),
NATIVE_METHOD(NativeCrypto, SSL_get_certificate, "(J)[[B"),
NATIVE_METHOD(NativeCrypto, SSL_get_peer_cert_chain, "(J)[[B"),
@@ -8005,30 +8136,86 @@
NATIVE_METHOD(NativeCrypto, SSL_CTX_enable_npn, "(J)V"),
NATIVE_METHOD(NativeCrypto, SSL_CTX_disable_npn, "(J)V"),
NATIVE_METHOD(NativeCrypto, SSL_get_npn_negotiated_protocol, "(J)[B"),
+ NATIVE_METHOD(NativeCrypto, SSL_CTX_set_alpn_protos, "(J[B)I"),
+ NATIVE_METHOD(NativeCrypto, SSL_get0_alpn_selected, "(J)[B"),
NATIVE_METHOD(NativeCrypto, ERR_peek_last_error, "()J"),
};
-void register_org_apache_harmony_xnet_provider_jsse_NativeCrypto(JNIEnv* env) {
- JNI_TRACE("register_org_apache_harmony_xnet_provider_jsse_NativeCrypto");
- jniRegisterNativeMethods(env, "org/apache/harmony/xnet/provider/jsse/NativeCrypto",
+static void initialize_conscrypt(JNIEnv* env) {
+ jniRegisterNativeMethods(env, TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/NativeCrypto",
sNativeCryptoMethods, NELEM(sNativeCryptoMethods));
- env->GetJavaVM(&gJavaVM);
-
ScopedLocalRef<jclass> localClass(env,
- env->FindClass("org/apache/harmony/xnet/provider/jsse/OpenSSLBIOInputStream"));
+ env->FindClass(TO_STRING(JNI_JARJAR_PREFIX) "org/conscrypt/OpenSSLBIOInputStream"));
openSslOutputStreamClass = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
if (openSslOutputStreamClass == NULL) {
ALOGE("failed to find class OpenSSLBIOInputStream");
abort();
}
- calendar_setMethod = env->GetMethodID(JniConstants::calendarClass, "set", "(IIIIII)V");
- inputStream_readMethod = env->GetMethodID(JniConstants::inputStreamClass, "read", "([B)I");
- integer_valueOfMethod = env->GetStaticMethodID(JniConstants::integerClass, "valueOf",
+ calendar_setMethod = env->GetMethodID(calendarClass, "set", "(IIIIII)V");
+ inputStream_readMethod = env->GetMethodID(inputStreamClass, "read", "([B)I");
+ integer_valueOfMethod = env->GetStaticMethodID(integerClass, "valueOf",
"(I)Ljava/lang/Integer;");
openSslInputStream_readLineMethod = env->GetMethodID(openSslOutputStreamClass, "gets",
"([B)I");
- outputStream_writeMethod = env->GetMethodID(JniConstants::outputStreamClass, "write", "([B)V");
- outputStream_flushMethod = env->GetMethodID(JniConstants::outputStreamClass, "flush", "()V");
+ outputStream_writeMethod = env->GetMethodID(outputStreamClass, "write", "([B)V");
+ 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()));
+ if (result == NULL) {
+ ALOGE("failed to find class '%s'", name);
+ abort();
+ }
+ return result;
+}
+
+// Use JNI_OnLoad for when we're standalone
+int JNI_OnLoad(JavaVM *vm, void* reserved) {
+ JNI_TRACE("JNI_OnLoad NativeCrypto");
+ gJavaVM = vm;
+
+ JNIEnv *env;
+ if (vm->GetEnv((void**)&env, JNI_VERSION_1_6) != JNI_OK) {
+ ALOGE("Could not get JNIEnv");
+ return JNI_ERR;
+ }
+
+ byteArrayClass = findClass(env, "[B");
+ calendarClass = findClass(env, "java/util/Calendar");
+ inputStreamClass = findClass(env, "java/io/InputStream");
+ integerClass = findClass(env, "java/lang/Integer");
+ objectClass = findClass(env, "java/lang/Object");
+ objectArrayClass = findClass(env, "[Ljava/lang/Object;");
+ outputStreamClass = findClass(env, "java/io/OutputStream");
+ stringClass = findClass(env, "java/lang/String");
+
+ 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/main/native/sub.mk b/crypto/src/main/native/sub.mk
new file mode 100644
index 0000000..62f8672
--- /dev/null
+++ b/crypto/src/main/native/sub.mk
@@ -0,0 +1,18 @@
+# -*- mode: makefile -*-
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := \
+ org_conscrypt_NativeCrypto.cpp
+
+LOCAL_C_INCLUDES += \
+ libcore/luni/src/main/native
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+#LOCAL_SHARED_LIBRARIES +=
+
+#LOCAL_STATIC_LIBRARIES +=
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java b/crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java
rename to crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
index 8359c99..04890f6 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CertPinManagerTest.java
+++ b/crypto/src/test/java/org/conscrypt/CertPinManagerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.FileWriter;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java b/crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java
rename to crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
index 42585b9..7663789 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ChainStrengthAnalyzerTest.java
+++ b/crypto/src/test/java/org/conscrypt/ChainStrengthAnalyzerTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@@ -125,4 +125,4 @@
InputStream pemInput = new ByteArrayInputStream(pem.getBytes());
return (X509Certificate) cf.generateCertificate(pemInput);
}
-}
\ No newline at end of file
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java b/crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
similarity index 97%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
rename to crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
index 7adecaf..970ad34 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/CipherSuiteTest.java
+++ b/crypto/src/test/java/org/conscrypt/CipherSuiteTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.MessageDigest;
import java.util.ArrayList;
@@ -24,7 +24,6 @@
import javax.crypto.Mac;
import junit.framework.TestCase;
import libcore.java.security.StandardNames;
-import org.apache.harmony.xnet.provider.jsse.CipherSuite;
public class CipherSuiteTest extends TestCase {
public void test_getByName() throws Exception {
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java b/crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
similarity index 98%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
rename to crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
index 6d17a25..93037db 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/ClientSessionContextTest.java
+++ b/crypto/src/test/java/org/conscrypt/ClientSessionContextTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.util.Enumeration;
import java.util.HashSet;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java b/crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
similarity index 97%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
rename to crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
index 9714cc3..9d7e2ec 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/FileClientSessionCacheTest.java
+++ b/crypto/src/test/java/org/conscrypt/FileClientSessionCacheTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.IOException;
diff --git a/crypto/src/test/java/org/conscrypt/MacTest.java b/crypto/src/test/java/org/conscrypt/MacTest.java
new file mode 100644
index 0000000..304ecdb
--- /dev/null
+++ b/crypto/src/test/java/org/conscrypt/MacTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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 org.conscrypt;
+
+import java.security.Provider;
+import java.security.Security;
+import java.util.Arrays;
+
+import javax.crypto.Mac;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+
+import junit.framework.TestCase;
+
+public class MacTest extends TestCase {
+ public void test_getInstance_OpenSSL_ENGINE() throws Exception {
+ final String secret = "-HMAC-test1";
+ final byte[] testString = "testing123".getBytes();
+
+ Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
+ NativeCryptoTest.loadTestEngine();
+ OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
+
+ /*
+ * The "-HMAC-" prefix is a special prefix recognized by
+ * test_openssl_engine.cpp
+ */
+ SecretKey key1 = engine.getSecretKeyById(secret, "HmacSHA256");
+ SecretKey key1dupe = engine.getSecretKeyById(secret, "HmacSHA256");
+
+ /* Non-ENGINE-based SecretKey */
+ SecretKey key2 = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
+
+ /* The one that is ENGINE-based can't be equal to a non-ENGINE one. */
+ assertFalse(key1.equals(key2));
+ assertEquals(key1, key1dupe);
+ assertNull(key1.getFormat());
+ assertNull(key1.getEncoded());
+ assertEquals("RAW", key2.getFormat());
+ assertEquals(Arrays.toString(secret.getBytes()), Arrays.toString(key2.getEncoded()));
+
+ Mac mac1 = Mac.getInstance("HmacSHA256", p);
+ mac1.init(key1);
+ mac1.update(testString);
+ byte[] output1 = mac1.doFinal();
+ assertEquals(mac1.getMacLength(), output1.length);
+
+ Mac mac2 = Mac.getInstance("HmacSHA256", p);
+ mac2.init(key2);
+ mac2.update(testString);
+ byte[] output2 = mac2.doFinal();
+
+ assertEquals(Arrays.toString(output2), Arrays.toString(output1));
+ }
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
similarity index 94%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
rename to crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
index f456f3e..8692f8a 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/NativeCryptoTest.java
+++ b/crypto/src/test/java/org/conscrypt/NativeCryptoTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import dalvik.system.BaseDexClassLoader;
import java.io.ByteArrayInputStream;
@@ -29,7 +29,6 @@
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
-import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
@@ -53,8 +52,8 @@
import libcore.io.IoUtils;
import libcore.java.security.StandardNames;
import libcore.java.security.TestKeyStore;
-import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks;
-import static org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
+import org.conscrypt.NativeCrypto.SSLHandshakeCallbacks;
+import static org.conscrypt.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
public class NativeCryptoTest extends TestCase {
/** Corresponds to the native test library "libjavacoretests.so" */
@@ -67,12 +66,12 @@
private static final long TIMEOUT_SECONDS = 5;
- private static byte[] SERVER_PRIVATE_KEY;
+ private static OpenSSLKey SERVER_PRIVATE_KEY;
private static byte[][] SERVER_CERTIFICATES;
- private static byte[] CLIENT_PRIVATE_KEY;
+ private static OpenSSLKey CLIENT_PRIVATE_KEY;
private static byte[][] CLIENT_CERTIFICATES;
private static byte[][] CA_PRINCIPALS;
- private static PrivateKey CHANNEL_ID_PRIVATE_KEY;
+ private static OpenSSLKey CHANNEL_ID_PRIVATE_KEY;
private static byte[] CHANNEL_ID;
@Override
@@ -80,7 +79,7 @@
assertEquals(0, NativeCrypto.ERR_peek_last_error());
}
- private static byte[] getServerPrivateKey() {
+ private static OpenSSLKey getServerPrivateKey() {
initCerts();
return SERVER_PRIVATE_KEY;
}
@@ -90,7 +89,7 @@
return SERVER_CERTIFICATES;
}
- private static byte[] getClientPrivateKey() {
+ private static OpenSSLKey getClientPrivateKey() {
initCerts();
return CLIENT_PRIVATE_KEY;
}
@@ -116,13 +115,13 @@
try {
PrivateKeyEntry serverPrivateKeyEntry
= TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
- SERVER_PRIVATE_KEY = serverPrivateKeyEntry.getPrivateKey().getEncoded();
+ SERVER_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(serverPrivateKeyEntry.getPrivateKey());
SERVER_CERTIFICATES = NativeCrypto.encodeCertificates(
serverPrivateKeyEntry.getCertificateChain());
PrivateKeyEntry clientPrivateKeyEntry
= TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
- CLIENT_PRIVATE_KEY = clientPrivateKeyEntry.getPrivateKey().getEncoded();
+ CLIENT_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(clientPrivateKeyEntry.getPrivateKey());
CLIENT_CERTIFICATES = NativeCrypto.encodeCertificates(
clientPrivateKeyEntry.getCertificateChain());
@@ -147,7 +146,7 @@
BigInteger s = new BigInteger(
"229cdbbf489aea584828a261a23f9ff8b0f66f7ccac98bf2096ab3aee41497c5", 16);
CHANNEL_ID_PRIVATE_KEY = new OpenSSLECPrivateKey(
- new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec()));
+ new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec())).getOpenSSLKey();
// Channel ID is the concatenation of the X and Y coordinates of the public key.
CHANNEL_ID = new BigInteger(
@@ -339,7 +338,7 @@
public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
try {
- NativeCrypto.SSL_set1_tls_channel_id(NULL, null);
+ NativeCrypto.SSL_set1_tls_channel_id(NULL, NULL);
fail();
} catch (NullPointerException expected) {
}
@@ -348,25 +347,14 @@
long s = NativeCrypto.SSL_new(c);
try {
- NativeCrypto.SSL_set1_tls_channel_id(s, null);
+ NativeCrypto.SSL_set1_tls_channel_id(s, NULL);
fail();
} catch (NullPointerException expected) {
}
- // Use the key via the wrapper that decides whether to use PKCS#8 or native OpenSSL.
- NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY);
-
- // Use the key via its PKCS#8 representation.
- assertEquals("PKCS#8", CHANNEL_ID_PRIVATE_KEY.getFormat());
- byte[] pkcs8EncodedKeyBytes = CHANNEL_ID_PRIVATE_KEY.getEncoded();
- assertNotNull(pkcs8EncodedKeyBytes);
- NativeCrypto.SSL_use_PKCS8_PrivateKey_for_tls_channel_id(s, pkcs8EncodedKeyBytes);
-
// Use the key natively. This works because the initChannelIdKey method ensures that the
// key is backed by OpenSSL.
- NativeCrypto.SSL_use_OpenSSL_PrivateKey_for_tls_channel_id(
- s,
- ((OpenSSLECPrivateKey) CHANNEL_ID_PRIVATE_KEY).getOpenSSLKey().getPkeyContext());
+ NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY.getPkeyContext());
NativeCrypto.SSL_free(s);
NativeCrypto.SSL_CTX_free(c);
@@ -374,7 +362,7 @@
public void test_SSL_use_PrivateKey() throws Exception {
try {
- NativeCrypto.SSL_use_PrivateKey(NULL, null);
+ NativeCrypto.SSL_use_PrivateKey(NULL, NULL);
fail();
} catch (NullPointerException expected) {
}
@@ -383,12 +371,12 @@
long s = NativeCrypto.SSL_new(c);
try {
- NativeCrypto.SSL_use_PrivateKey(s, null);
+ NativeCrypto.SSL_use_PrivateKey(s, NULL);
fail();
} catch (NullPointerException expected) {
}
- NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+ NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
NativeCrypto.SSL_free(s);
NativeCrypto.SSL_CTX_free(c);
@@ -430,7 +418,7 @@
} catch (SSLException expected) {
}
- NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+ NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
NativeCrypto.SSL_check_private_key(s);
NativeCrypto.SSL_free(s);
@@ -441,7 +429,7 @@
long s = NativeCrypto.SSL_new(c);
// first private, then certificate
- NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
+ NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
try {
NativeCrypto.SSL_check_private_key(s);
@@ -613,7 +601,7 @@
private static final boolean DEBUG = false;
public static class Hooks {
- private PrivateKey channelIdPrivateKey;
+ private OpenSSLKey channelIdPrivateKey;
public long getContext() throws SSLException {
return NativeCrypto.SSL_CTX_new();
@@ -626,7 +614,7 @@
NativeCrypto.SSL_set_cipher_lists(s, new String[] { "RC4-MD5" });
if (channelIdPrivateKey != null) {
- NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey);
+ NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey.getPkeyContext());
}
return s;
}
@@ -721,13 +709,13 @@
}
public static class ServerHooks extends Hooks {
- private final byte[] privateKey;
+ private final OpenSSLKey privateKey;
private final byte[][] certificates;
private boolean channelIdEnabled;
private byte[] channelIdAfterHandshake;
private Throwable channelIdAfterHandshakeException;
- public ServerHooks(byte[] privateKey, byte[][] certificates) {
+ public ServerHooks(OpenSSLKey privateKey, byte[][] certificates) {
this.privateKey = privateKey;
this.certificates = certificates;
}
@@ -736,7 +724,7 @@
public long beforeHandshake(long c) throws SSLException {
long s = super.beforeHandshake(c);
if (privateKey != null) {
- NativeCrypto.SSL_use_PrivateKey(s, privateKey);
+ NativeCrypto.SSL_use_PrivateKey(s, privateKey.getPkeyContext());
}
if (certificates != null) {
NativeCrypto.SSL_use_certificate(s, certificates);
@@ -768,7 +756,8 @@
}
public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
- final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols) {
+ final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols,
+ final byte[] alpnProtocols) {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<TestSSLHandshakeCallbacks> future = executor.submit(
new Callable<TestSSLHandshakeCallbacks>() {
@@ -797,7 +786,7 @@
long session = NULL;
try {
session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
- npnProtocols);
+ npnProtocols, alpnProtocols);
if (DEBUG) {
System.out.println("ssl=0x" + Long.toString(s, 16)
+ " handshake"
@@ -816,7 +805,7 @@
public void test_SSL_do_handshake_NULL_SSL() throws Exception {
try {
- NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null);
+ NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null, null);
fail();
} catch (NullPointerException expected) {
}
@@ -827,13 +816,13 @@
long s = NativeCrypto.SSL_new(c);
try {
- NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null);
+ NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null, null);
fail();
} catch (NullPointerException expected) {
}
try {
- NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null);
+ NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null, null);
fail();
} catch (NullPointerException expected) {
}
@@ -847,8 +836,8 @@
final ServerSocket listener = new ServerSocket(0);
Hooks cHooks = new Hooks();
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -870,7 +859,7 @@
@Override
public void clientCertificateRequested(long s) {
super.clientCertificateRequested(s);
- NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey());
+ NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey().getPkeyContext());
NativeCrypto.SSL_use_certificate(s, getClientCertificates());
}
};
@@ -883,8 +872,8 @@
return s;
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -928,8 +917,10 @@
return s;
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
} catch (ExecutionException expected) {
@@ -991,8 +982,8 @@
}
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
try {
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
} catch (ExecutionException e) {
@@ -1010,8 +1001,10 @@
try {
Hooks cHooks = new Hooks();
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null,
+ null);
serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
@@ -1033,8 +1026,8 @@
try {
Hooks cHooks = new Hooks();
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null, null);
clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
@@ -1055,8 +1048,8 @@
cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
sHooks.channelIdEnabled = true;
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1081,8 +1074,8 @@
cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
sHooks.channelIdEnabled = false;
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1107,8 +1100,8 @@
cHooks.channelIdPrivateKey = null;
ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
sHooks.channelIdEnabled = true;
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
assertTrue(clientCallback.verifyCertificateChainCalled);
@@ -1175,9 +1168,9 @@
}
};
Future<TestSSLHandshakeCallbacks> client
- = handshake(listener, 0, true, cHooks, null);
+ = handshake(listener, 0, true, cHooks, null, null);
Future<TestSSLHandshakeCallbacks> server
- = handshake(listener, 0, false, sHooks, null);
+ = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1218,9 +1211,9 @@
}
};
Future<TestSSLHandshakeCallbacks> client
- = handshake(listener, 0, true, cHooks, null);
+ = handshake(listener, 0, true, cHooks, null, null);
Future<TestSSLHandshakeCallbacks> server
- = handshake(listener, 0, false, sHooks, null);
+ = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1260,8 +1253,10 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
} catch (ExecutionException expected) {
@@ -1279,8 +1274,10 @@
return s;
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
} catch (ExecutionException expected) {
@@ -1347,8 +1344,8 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1396,9 +1393,59 @@
ServerSocket listener = new ServerSocket(0);
Future<TestSSLHandshakeCallbacks> client
- = handshake(listener, 0, true, cHooks, clientNpnProtocols);
+ = handshake(listener, 0, true, cHooks, clientNpnProtocols, null);
Future<TestSSLHandshakeCallbacks> server
- = handshake(listener, 0, false, sHooks, serverNpnProtocols);
+ = handshake(listener, 0, false, sHooks, serverNpnProtocols, null);
+ client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ }
+
+ public void test_SSL_AlpnNegotiateSuccess() throws Exception {
+ final byte[] clientAlpnProtocols = new byte[] {
+ 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
+ 3, 'f', 'o', 'o',
+ 6, 's', 'p', 'd', 'y', '/', '2',
+ };
+ final byte[] serverAlpnProtocols = new byte[] {
+ 6, 's', 'p', 'd', 'y', '/', '2',
+ 3, 'f', 'o', 'o',
+ 3, 'b', 'a', 'r',
+ };
+
+ Hooks cHooks = new Hooks() {
+ @Override public long beforeHandshake(long context) throws SSLException {
+ NativeCrypto.SSL_CTX_set_alpn_protos(context, clientAlpnProtocols);
+ return super.beforeHandshake(context);
+ }
+ @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
+ FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
+ byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
+ assertEquals("spdy/2", new String(negotiated));
+ /*
+ * There is no callback on the client, so we can't enable
+ * cut-through
+ */
+ assertEquals("ALPN should not enable cutthrough on the client", 0,
+ NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
+ super.afterHandshake(session, ssl, context, socket, fd, callback);
+ }
+ };
+ Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
+ @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
+ FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
+ byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
+ assertEquals("spdy/2", new String(negotiated));
+ assertEquals("ALPN should not enable cutthrough on the server",
+ 0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
+ super.afterHandshake(session, ssl, c, sock, fd, callback);
+ }
+ };
+
+ ServerSocket listener = new ServerSocket(0);
+ Future<TestSSLHandshakeCallbacks> client
+ = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server
+ = handshake(listener, 0, false, sHooks, null, serverAlpnProtocols);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1451,8 +1498,8 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1487,8 +1534,8 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1514,8 +1561,8 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1618,8 +1665,10 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1646,8 +1695,10 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
fail();
} catch (ExecutionException expected) {
@@ -1761,8 +1812,8 @@
super.afterHandshake(session, s, c, sock, fd, callback);
}
};
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1835,8 +1886,8 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1864,8 +1915,10 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
+ null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
+ null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1892,8 +1945,8 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1919,8 +1972,8 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
@@ -1966,8 +2019,8 @@
}
};
Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
- Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
- Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
+ Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
+ Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java b/crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
similarity index 92%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java
rename to crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
index 76e423c..045c509 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/OpenSSLSignatureTest.java
+++ b/crypto/src/test/java/org/conscrypt/OpenSSLSignatureTest.java
@@ -14,11 +14,10 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.security.NoSuchAlgorithmException;
import junit.framework.TestCase;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSignature;
public class OpenSSLSignatureTest extends TestCase {
diff --git a/crypto/src/test/java/org/conscrypt/SignatureTest.java b/crypto/src/test/java/org/conscrypt/SignatureTest.java
new file mode 100644
index 0000000..d6679c4
--- /dev/null
+++ b/crypto/src/test/java/org/conscrypt/SignatureTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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 org.conscrypt;
+
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.Signature;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Set;
+import junit.framework.TestCase;
+
+public class SignatureTest extends TestCase {
+ // 20 bytes for DSA
+ private final byte[] DATA = new byte[20];
+
+ public void test_getInstance_OpenSSL_ENGINE() throws Exception {
+ final String pem_private = "-----BEGIN RSA PRIVATE KEY-----\n"
+ + "MIICXAIBAAKBgQDpm4KamxulJnycEzNONGM7p0CvAaoZxJEd5Dvio5b6BROdCtRN\n"
+ + "lEsB+9vtB5thkyDVC7N+IW0AjtyDE6h2QP+AWa+c4dh0RM2uNVXkUWPrA8C++GHv\n"
+ + "EDlxZzRGiQEMuippYfIyBVkO+4+GRvnkG4dKjzxrQYPqKUK3C4PgFW2FewIDAQAB\n"
+ + "AoGAGUTSBsk6X03fcr588TundD9uNr/2V1002Ufj1msdnKPJ8FXIiy+8QVWt/2Cw\n"
+ + "RQi2J3VhkAYrlUDex2rr8Qas3E9uuwKgg/MZ4EsJbnKKgkd7uBZfmZ2ogcNJ82u7\n"
+ + "teVijFpdsVLDa9aczEppt5sZzyTaBrovrRb+AIRDpMw3I0ECQQD3JkWeQUA9Is1V\n"
+ + "z0X/ly/kaQKQLlrwYNdiKF0qOpyTLAguI7asAS72Zj7fThk5bHLM+mmgYwkicIIb\n"
+ + "67J32GQbAkEA8fkXqEnwMFYSkRmT9M/qUkwWUsMW12/AoZFI5gwKNDHZYxytGGLw\n"
+ + "mC//0qKnyeUG00vz06vLApe4/Sq4ODe6IQJBALEGastF9ZtUuDsEciD2y8kRJlLb\n"
+ + "wSt4Ug3u13yN6uTHnzxdPFTLrDW1WsdcC1lEQp5rpwjIpxxR9f/FvVl2V40CQHOY\n"
+ + "F6EhkUjGFaCTo4b0PHCMQK3Q3PyWOmP0z+p2HfnJRpx+eoKH4YASjhfF9HoSmywd\n"
+ + "wKGCFD1s1ca7vb29gYECQH86GmYZsDoLNWurEVJbkmCr7X1+xwim6umdrNKR27P7\n"
+ + "F1y0Sa3YY+LiiRb+IRSWE/onlP+28LIzWGF4lcTfDMc=\n"
+ + "-----END RSA PRIVATE KEY-----";
+
+ final byte[] der_public = new byte[] {
+ (byte) 0x30, (byte) 0x81, (byte) 0x9F, (byte) 0x30, (byte) 0x0D, (byte) 0x06,
+ (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7,
+ (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00,
+ (byte) 0x03, (byte) 0x81, (byte) 0x8D, (byte) 0x00, (byte) 0x30, (byte) 0x81,
+ (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xE9,
+ (byte) 0x9B, (byte) 0x82, (byte) 0x9A, (byte) 0x9B, (byte) 0x1B, (byte) 0xA5,
+ (byte) 0x26, (byte) 0x7C, (byte) 0x9C, (byte) 0x13, (byte) 0x33, (byte) 0x4E,
+ (byte) 0x34, (byte) 0x63, (byte) 0x3B, (byte) 0xA7, (byte) 0x40, (byte) 0xAF,
+ (byte) 0x01, (byte) 0xAA, (byte) 0x19, (byte) 0xC4, (byte) 0x91, (byte) 0x1D,
+ (byte) 0xE4, (byte) 0x3B, (byte) 0xE2, (byte) 0xA3, (byte) 0x96, (byte) 0xFA,
+ (byte) 0x05, (byte) 0x13, (byte) 0x9D, (byte) 0x0A, (byte) 0xD4, (byte) 0x4D,
+ (byte) 0x94, (byte) 0x4B, (byte) 0x01, (byte) 0xFB, (byte) 0xDB, (byte) 0xED,
+ (byte) 0x07, (byte) 0x9B, (byte) 0x61, (byte) 0x93, (byte) 0x20, (byte) 0xD5,
+ (byte) 0x0B, (byte) 0xB3, (byte) 0x7E, (byte) 0x21, (byte) 0x6D, (byte) 0x00,
+ (byte) 0x8E, (byte) 0xDC, (byte) 0x83, (byte) 0x13, (byte) 0xA8, (byte) 0x76,
+ (byte) 0x40, (byte) 0xFF, (byte) 0x80, (byte) 0x59, (byte) 0xAF, (byte) 0x9C,
+ (byte) 0xE1, (byte) 0xD8, (byte) 0x74, (byte) 0x44, (byte) 0xCD, (byte) 0xAE,
+ (byte) 0x35, (byte) 0x55, (byte) 0xE4, (byte) 0x51, (byte) 0x63, (byte) 0xEB,
+ (byte) 0x03, (byte) 0xC0, (byte) 0xBE, (byte) 0xF8, (byte) 0x61, (byte) 0xEF,
+ (byte) 0x10, (byte) 0x39, (byte) 0x71, (byte) 0x67, (byte) 0x34, (byte) 0x46,
+ (byte) 0x89, (byte) 0x01, (byte) 0x0C, (byte) 0xBA, (byte) 0x2A, (byte) 0x69,
+ (byte) 0x61, (byte) 0xF2, (byte) 0x32, (byte) 0x05, (byte) 0x59, (byte) 0x0E,
+ (byte) 0xFB, (byte) 0x8F, (byte) 0x86, (byte) 0x46, (byte) 0xF9, (byte) 0xE4,
+ (byte) 0x1B, (byte) 0x87, (byte) 0x4A, (byte) 0x8F, (byte) 0x3C, (byte) 0x6B,
+ (byte) 0x41, (byte) 0x83, (byte) 0xEA, (byte) 0x29, (byte) 0x42, (byte) 0xB7,
+ (byte) 0x0B, (byte) 0x83, (byte) 0xE0, (byte) 0x15, (byte) 0x6D, (byte) 0x85,
+ (byte) 0x7B, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01
+ };
+
+ // We only need to test this on the OpenSSL provider.
+ Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
+
+ /* ENGINE-based private key */
+ NativeCryptoTest.loadTestEngine();
+ OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
+ PrivateKey privKey = engine.getPrivateKeyById(pem_private);
+ assertTrue(privKey instanceof RSAPrivateKey);
+
+ /* Non-ENGINE-based public key */
+ KeyFactory kf = KeyFactory.getInstance("RSA", p);
+ PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(der_public));
+
+ KeyPair kp = new KeyPair(pubKey, privKey);
+
+ Set<Provider.Service> services = p.getServices();
+ for (Provider.Service service : services) {
+ if ("Signature".equals(service.getType()) && service.getAlgorithm().contains("RSA")) {
+ Signature sig1 = Signature.getInstance(service.getAlgorithm(), p);
+ test_Signature(sig1, kp);
+ }
+ }
+ }
+
+ private void test_Signature(Signature sig, KeyPair keyPair) throws Exception {
+ sig.initSign(keyPair.getPrivate());
+ sig.update(DATA);
+ byte[] signature = sig.sign();
+ assertNotNull(sig.getAlgorithm(), signature);
+ assertTrue(sig.getAlgorithm(), signature.length > 0);
+
+ sig.initVerify(keyPair.getPublic());
+ sig.update(DATA);
+ assertTrue(sig.getAlgorithm(), sig.verify(signature));
+
+ // After verify, should be reusable as if we are after initVerify
+ sig.update(DATA);
+ assertTrue(sig.getAlgorithm(), sig.verify(signature));
+
+ // Calling Signature.verify a second time should not throw
+ // http://code.google.com/p/android/issues/detail?id=34933
+ sig.verify(signature);
+ }
+}
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java b/crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
similarity index 99%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java
rename to crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
index 9757bc5..639ed95 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustManagerImplTest.java
+++ b/crypto/src/test/java/org/conscrypt/TrustManagerImplTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.FileWriter;
diff --git a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java b/crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
similarity index 99%
rename from luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java
rename to crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
index 8f9b7fa..a8e9475 100644
--- a/luni/src/test/java/org/apache/harmony/xnet/provider/jsse/TrustedCertificateStoreTest.java
+++ b/crypto/src/test/java/org/conscrypt/TrustedCertificateStoreTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.conscrypt;
import java.io.File;
import java.io.FileOutputStream;
diff --git a/dalvik/src/main/java/dalvik/annotation/KnownFailure.java b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
index 11e813d..1d47a72 100644
--- a/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
+++ b/dalvik/src/main/java/dalvik/annotation/KnownFailure.java
@@ -23,7 +23,7 @@
/**
* Marks a test case as a known failure. This means the underlying
- * implementation should be fixed. Seems to be similar to @code{@ToBeFixed}, so
+ * implementation should be fixed. Seems to be similar to {@code @ToBeFixed}, so
* maybe the two can be merged at some point.
*
* @hide
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTarget.java b/dalvik/src/main/java/dalvik/annotation/TestTarget.java
index dcfd20ca..a2f94a1 100644
--- a/dalvik/src/main/java/dalvik/annotation/TestTarget.java
+++ b/dalvik/src/main/java/dalvik/annotation/TestTarget.java
@@ -26,7 +26,7 @@
* specifies a single method target for the test (but can be used multiple
* times).
*
- * @deprecated Obsolete
+ * @deprecated Obsolete.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE })
diff --git a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
index e88040e..1e16d0c 100644
--- a/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
+++ b/dalvik/src/main/java/dalvik/annotation/TestTargetClass.java
@@ -27,7 +27,7 @@
* organized according to the API classes they test. Might be too strict for
* some cases.
*
- * @deprecated Obsolete
+ * @deprecated Obsolete.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
diff --git a/dalvik/src/main/java/dalvik/system/BlockGuard.java b/dalvik/src/main/java/dalvik/system/BlockGuard.java
index d61f0e1..b9de236 100644
--- a/dalvik/src/main/java/dalvik/system/BlockGuard.java
+++ b/dalvik/src/main/java/dalvik/system/BlockGuard.java
@@ -22,7 +22,6 @@
import java.io.IOException;
import java.math.BigInteger;
import java.net.SocketException;
-import java.nio.charset.Charsets;
/**
* Mechanism to let threads set restrictions on what code is allowed
diff --git a/dalvik/src/main/java/dalvik/system/Zygote.java b/dalvik/src/main/java/dalvik/system/Zygote.java
index 9e96204..ea9dbdc 100644
--- a/dalvik/src/main/java/dalvik/system/Zygote.java
+++ b/dalvik/src/main/java/dalvik/system/Zygote.java
@@ -119,7 +119,7 @@
* dimension having a length of 3 and representing
* (resource, rlim_cur, rlim_max). These are set via the posix
* setrlimit(2) call.
- * @param seInfo null-ok a string specifying SEAndroid information for
+ * @param seInfo null-ok a string specifying SELinux information for
* the new process.
* @param niceName null-ok a string specifying the process name.
*
diff --git a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
index 11735eb..52f22a8 100644
--- a/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
+++ b/dalvik/src/main/native/org_apache_harmony_dalvik_NativeTestTarget.cpp
@@ -17,7 +17,7 @@
#define LOG_TAG "NativeTestTarget"
#include "JNIHelp.h"
-#include "../../../../luni/src/main/native/JniConstants.h"
+#include "JniConstants.h"
static void NativeTestTarget_emptyJniMethod0(JNIEnv*, jobject) { }
static void NativeTestTarget_emptyJniMethod6(JNIEnv*, jclass, int, int, int, int, int, int) { }
diff --git a/dex/src/main/java/com/android/dex/Annotation.java b/dex/src/main/java/com/android/dex/Annotation.java
new file mode 100644
index 0000000..e5ef978
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Annotation.java
@@ -0,0 +1,63 @@
+/*
+ * 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 com.android.dex;
+
+import static com.android.dex.EncodedValueReader.ENCODED_ANNOTATION;
+
+/**
+ * An annotation.
+ */
+public final class Annotation implements Comparable<Annotation> {
+ private final Dex dex;
+ private final byte visibility;
+ private final EncodedValue encodedAnnotation;
+
+ public Annotation(Dex dex, byte visibility, EncodedValue encodedAnnotation) {
+ this.dex = dex;
+ this.visibility = visibility;
+ this.encodedAnnotation = encodedAnnotation;
+ }
+
+ public byte getVisibility() {
+ return visibility;
+ }
+
+ public EncodedValueReader getReader() {
+ return new EncodedValueReader(encodedAnnotation, ENCODED_ANNOTATION);
+ }
+
+ public int getTypeIndex() {
+ EncodedValueReader reader = getReader();
+ reader.readAnnotation();
+ return reader.getAnnotationType();
+ }
+
+ public void writeTo(Dex.Section out) {
+ out.writeByte(visibility);
+ encodedAnnotation.writeTo(out);
+ }
+
+ @Override public int compareTo(Annotation other) {
+ return encodedAnnotation.compareTo(other.encodedAnnotation);
+ }
+
+ @Override public String toString() {
+ return dex == null
+ ? visibility + " " + getTypeIndex()
+ : visibility + " " + dex.typeNames().get(getTypeIndex());
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/ClassData.java b/dex/src/main/java/com/android/dex/ClassData.java
new file mode 100644
index 0000000..840756c
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ClassData.java
@@ -0,0 +1,104 @@
+/*
+ * 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 com.android.dex;
+
+public final class ClassData {
+ private final Field[] staticFields;
+ private final Field[] instanceFields;
+ private final Method[] directMethods;
+ private final Method[] virtualMethods;
+
+ public ClassData(Field[] staticFields, Field[] instanceFields,
+ Method[] directMethods, Method[] virtualMethods) {
+ this.staticFields = staticFields;
+ this.instanceFields = instanceFields;
+ this.directMethods = directMethods;
+ this.virtualMethods = virtualMethods;
+ }
+
+ public Field[] getStaticFields() {
+ return staticFields;
+ }
+
+ public Field[] getInstanceFields() {
+ return instanceFields;
+ }
+
+ public Method[] getDirectMethods() {
+ return directMethods;
+ }
+
+ public Method[] getVirtualMethods() {
+ return virtualMethods;
+ }
+
+ public Field[] allFields() {
+ Field[] result = new Field[staticFields.length + instanceFields.length];
+ System.arraycopy(staticFields, 0, result, 0, staticFields.length);
+ System.arraycopy(instanceFields, 0, result, staticFields.length, instanceFields.length);
+ return result;
+ }
+
+ public Method[] allMethods() {
+ Method[] result = new Method[directMethods.length + virtualMethods.length];
+ System.arraycopy(directMethods, 0, result, 0, directMethods.length);
+ System.arraycopy(virtualMethods, 0, result, directMethods.length, virtualMethods.length);
+ return result;
+ }
+
+ public static class Field {
+ private final int fieldIndex;
+ private final int accessFlags;
+
+ public Field(int fieldIndex, int accessFlags) {
+ this.fieldIndex = fieldIndex;
+ this.accessFlags = accessFlags;
+ }
+
+ public int getFieldIndex() {
+ return fieldIndex;
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+ }
+
+ public static class Method {
+ private final int methodIndex;
+ private final int accessFlags;
+ private final int codeOffset;
+
+ public Method(int methodIndex, int accessFlags, int codeOffset) {
+ this.methodIndex = methodIndex;
+ this.accessFlags = accessFlags;
+ this.codeOffset = codeOffset;
+ }
+
+ public int getMethodIndex() {
+ return methodIndex;
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ public int getCodeOffset() {
+ return codeOffset;
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/ClassDef.java b/dex/src/main/java/com/android/dex/ClassDef.java
new file mode 100644
index 0000000..b3225ec
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ClassDef.java
@@ -0,0 +1,102 @@
+/*
+ * 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 com.android.dex;
+
+/**
+ * A type definition.
+ */
+public final class ClassDef {
+ public static final int NO_INDEX = -1;
+ private final Dex buffer;
+ private final int offset;
+ private final int typeIndex;
+ private final int accessFlags;
+ private final int supertypeIndex;
+ private final int interfacesOffset;
+ private final int sourceFileIndex;
+ private final int annotationsOffset;
+ private final int classDataOffset;
+ private final int staticValuesOffset;
+
+ public ClassDef(Dex buffer, int offset, int typeIndex, int accessFlags,
+ int supertypeIndex, int interfacesOffset, int sourceFileIndex,
+ int annotationsOffset, int classDataOffset, int staticValuesOffset) {
+ this.buffer = buffer;
+ this.offset = offset;
+ this.typeIndex = typeIndex;
+ this.accessFlags = accessFlags;
+ this.supertypeIndex = supertypeIndex;
+ this.interfacesOffset = interfacesOffset;
+ this.sourceFileIndex = sourceFileIndex;
+ this.annotationsOffset = annotationsOffset;
+ this.classDataOffset = classDataOffset;
+ this.staticValuesOffset = staticValuesOffset;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+
+ public int getTypeIndex() {
+ return typeIndex;
+ }
+
+ public int getSupertypeIndex() {
+ return supertypeIndex;
+ }
+
+ public int getInterfacesOffset() {
+ return interfacesOffset;
+ }
+
+ public short[] getInterfaces() {
+ return buffer.readTypeList(interfacesOffset).getTypes();
+ }
+
+ public int getAccessFlags() {
+ return accessFlags;
+ }
+
+ public int getSourceFileIndex() {
+ return sourceFileIndex;
+ }
+
+ public int getAnnotationsOffset() {
+ return annotationsOffset;
+ }
+
+ public int getClassDataOffset() {
+ return classDataOffset;
+ }
+
+ public int getStaticValuesOffset() {
+ return staticValuesOffset;
+ }
+
+ @Override public String toString() {
+ if (buffer == null) {
+ return typeIndex + " " + supertypeIndex;
+ }
+
+ StringBuilder result = new StringBuilder();
+ result.append(buffer.typeNames().get(typeIndex));
+ if (supertypeIndex != NO_INDEX) {
+ result.append(" extends ").append(buffer.typeNames().get(supertypeIndex));
+ }
+ return result.toString();
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/Code.java b/dex/src/main/java/com/android/dex/Code.java
new file mode 100644
index 0000000..9258af7
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Code.java
@@ -0,0 +1,124 @@
+/*
+ * 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 com.android.dex;
+
+public final class Code {
+ private final int registersSize;
+ private final int insSize;
+ private final int outsSize;
+ private final int debugInfoOffset;
+ private final short[] instructions;
+ private final Try[] tries;
+ private final CatchHandler[] catchHandlers;
+
+ public Code(int registersSize, int insSize, int outsSize, int debugInfoOffset,
+ short[] instructions, Try[] tries, CatchHandler[] catchHandlers) {
+ this.registersSize = registersSize;
+ this.insSize = insSize;
+ this.outsSize = outsSize;
+ this.debugInfoOffset = debugInfoOffset;
+ this.instructions = instructions;
+ this.tries = tries;
+ this.catchHandlers = catchHandlers;
+ }
+
+ public int getRegistersSize() {
+ return registersSize;
+ }
+
+ public int getInsSize() {
+ return insSize;
+ }
+
+ public int getOutsSize() {
+ return outsSize;
+ }
+
+ public int getDebugInfoOffset() {
+ return debugInfoOffset;
+ }
+
+ public short[] getInstructions() {
+ return instructions;
+ }
+
+ public Try[] getTries() {
+ return tries;
+ }
+
+ public CatchHandler[] getCatchHandlers() {
+ return catchHandlers;
+ }
+
+ public static class Try {
+ final int startAddress;
+ final int instructionCount;
+ final int catchHandlerIndex;
+
+ Try(int startAddress, int instructionCount, int catchHandlerIndex) {
+ this.startAddress = startAddress;
+ this.instructionCount = instructionCount;
+ this.catchHandlerIndex = catchHandlerIndex;
+ }
+
+ public int getStartAddress() {
+ return startAddress;
+ }
+
+ public int getInstructionCount() {
+ return instructionCount;
+ }
+
+ /**
+ * Returns this try's catch handler <strong>index</strong>. Note that
+ * this is distinct from the its catch handler <strong>offset</strong>.
+ */
+ public int getCatchHandlerIndex() {
+ return catchHandlerIndex;
+ }
+ }
+
+ public static class CatchHandler {
+ final int[] typeIndexes;
+ final int[] addresses;
+ final int catchAllAddress;
+ final int offset;
+
+ public CatchHandler(int[] typeIndexes, int[] addresses, int catchAllAddress, int offset) {
+ this.typeIndexes = typeIndexes;
+ this.addresses = addresses;
+ this.catchAllAddress = catchAllAddress;
+ this.offset = offset;
+ }
+
+ public int[] getTypeIndexes() {
+ return typeIndexes;
+ }
+
+ public int[] getAddresses() {
+ return addresses;
+ }
+
+ public int getCatchAllAddress() {
+ return catchAllAddress;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/Dex.java b/dex/src/main/java/com/android/dex/Dex.java
new file mode 100644
index 0000000..29cd30e
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Dex.java
@@ -0,0 +1,791 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.Code.CatchHandler;
+import com.android.dex.Code.Try;
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+import com.android.dex.util.FileUtils;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UTFDataFormatException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.AbstractList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.RandomAccess;
+import java.util.zip.Adler32;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * The bytes of a dex file in memory for reading and writing. All int offsets
+ * are unsigned.
+ */
+public final class Dex {
+ private static final int CHECKSUM_OFFSET = 8;
+ private static final int CHECKSUM_SIZE = 4;
+ private static final int SIGNATURE_OFFSET = CHECKSUM_OFFSET + CHECKSUM_SIZE;
+ private static final int SIGNATURE_SIZE = 20;
+
+ 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;
+ }
+ };
+
+ /**
+ * Creates a new dex that reads from {@code data}. It is an error to modify
+ * {@code data} after using it to create a dex buffer.
+ */
+ public Dex(byte[] data) throws IOException {
+ this(ByteBuffer.wrap(data));
+ }
+
+ private Dex(ByteBuffer data) throws IOException {
+ this.data = data;
+ this.data.order(ByteOrder.LITTLE_ENDIAN);
+ this.tableOfContents.readFrom(this);
+ }
+
+ /**
+ * Creates a new empty dex of the specified size.
+ */
+ public Dex(int byteCount) throws IOException {
+ this.data = ByteBuffer.wrap(new byte[byteCount]);
+ this.data.order(ByteOrder.LITTLE_ENDIAN);
+ }
+
+ /**
+ * Creates a new dex buffer of the dex in {@code in}, and closes {@code in}.
+ */
+ public Dex(InputStream in) throws IOException {
+ loadFrom(in);
+ }
+
+ /**
+ * Creates a new dex buffer from the dex file {@code file}.
+ */
+ public Dex(File file) throws IOException {
+ if (FileUtils.hasArchiveSuffix(file.getName())) {
+ ZipFile zipFile = new ZipFile(file);
+ ZipEntry entry = zipFile.getEntry(DexFormat.DEX_IN_JAR_NAME);
+ if (entry != null) {
+ loadFrom(zipFile.getInputStream(entry));
+ zipFile.close();
+ } else {
+ throw new DexException("Expected " + DexFormat.DEX_IN_JAR_NAME + " in " + file);
+ }
+ } else if (file.getName().endsWith(".dex")) {
+ loadFrom(new FileInputStream(file));
+ } else {
+ throw new DexException("unknown output extension: " + file);
+ }
+ }
+
+ /**
+ * Creates a new dex from the contents of {@code bytes}. This API supports
+ * both {@code .dex} and {@code .odex} input. Calling this constructor
+ * transfers ownership of {@code bytes} to the returned Dex: it is an error
+ * to access the buffer after calling this method.
+ */
+ public static Dex create(ByteBuffer data) throws IOException {
+ data.order(ByteOrder.LITTLE_ENDIAN);
+
+ // if it's an .odex file, set position and limit to the .dex section
+ if (data.get(0) == 'd'
+ && data.get(1) == 'e'
+ && data.get(2) == 'y'
+ && data.get(3) == '\n') {
+ data.position(8);
+ int offset = data.getInt();
+ int length = data.getInt();
+ data.position(offset);
+ data.limit(offset + length);
+ data = data.slice();
+ }
+
+ return new Dex(data);
+ }
+
+ private void loadFrom(InputStream in) throws IOException {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ byte[] buffer = new byte[8192];
+
+ int count;
+ while ((count = in.read(buffer)) != -1) {
+ bytesOut.write(buffer, 0, count);
+ }
+ in.close();
+
+ this.data = ByteBuffer.wrap(bytesOut.toByteArray());
+ this.data.order(ByteOrder.LITTLE_ENDIAN);
+ this.tableOfContents.readFrom(this);
+ }
+
+ private static void checkBounds(int index, int length) {
+ if (index < 0 || index >= length) {
+ throw new IndexOutOfBoundsException("index:" + index + ", length=" + length);
+ }
+ }
+
+ public void writeTo(OutputStream out) throws IOException {
+ byte[] buffer = new byte[8192];
+ ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+ data.clear();
+ while (data.hasRemaining()) {
+ int count = Math.min(buffer.length, data.remaining());
+ data.get(buffer, 0, count);
+ out.write(buffer, 0, count);
+ }
+ }
+
+ public void writeTo(File dexOut) throws IOException {
+ OutputStream out = new FileOutputStream(dexOut);
+ writeTo(out);
+ out.close();
+ }
+
+ public TableOfContents getTableOfContents() {
+ return tableOfContents;
+ }
+
+ public Section open(int position) {
+ if (position < 0 || position >= data.capacity()) {
+ throw new IllegalArgumentException("position=" + position
+ + " length=" + data.capacity());
+ }
+ ByteBuffer sectionData = data.duplicate();
+ sectionData.order(ByteOrder.LITTLE_ENDIAN); // necessary?
+ sectionData.position(position);
+ sectionData.limit(data.capacity());
+ return new Section("section", sectionData);
+ }
+
+ public Section appendSection(int maxByteCount, String name) {
+ if ((maxByteCount & 3) != 0) {
+ throw new IllegalStateException("Not four byte aligned!");
+ }
+ int limit = nextSectionStart + maxByteCount;
+ ByteBuffer sectionData = data.duplicate();
+ sectionData.order(ByteOrder.LITTLE_ENDIAN); // necessary?
+ sectionData.position(nextSectionStart);
+ sectionData.limit(limit);
+ Section result = new Section(name, sectionData);
+ nextSectionStart = limit;
+ return result;
+ }
+
+ public int getLength() {
+ return data.capacity();
+ }
+
+ public int getNextSectionStart() {
+ return nextSectionStart;
+ }
+
+ /**
+ * Returns a copy of the the bytes of this dex.
+ */
+ public byte[] getBytes() {
+ ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+ byte[] result = new byte[data.capacity()];
+ data.position(0);
+ data.get(result);
+ return result;
+ }
+
+ public List<String> strings() {
+ return strings;
+ }
+
+ public List<Integer> typeIds() {
+ return typeIds;
+ }
+
+ public List<String> typeNames() {
+ return typeNames;
+ }
+
+ public List<ProtoId> protoIds() {
+ return protoIds;
+ }
+
+ public List<FieldId> fieldIds() {
+ return fieldIds;
+ }
+
+ public List<MethodId> methodIds() {
+ return methodIds;
+ }
+
+ 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();
+ }
+ };
+ }
+ };
+ }
+
+ public TypeList readTypeList(int offset) {
+ if (offset == 0) {
+ return TypeList.EMPTY;
+ }
+ return open(offset).readTypeList();
+ }
+
+ public ClassData readClassData(ClassDef classDef) {
+ int offset = classDef.getClassDataOffset();
+ if (offset == 0) {
+ throw new IllegalArgumentException("offset == 0");
+ }
+ return open(offset).readClassData();
+ }
+
+ public Code readCode(ClassData.Method method) {
+ int offset = method.getCodeOffset();
+ if (offset == 0) {
+ throw new IllegalArgumentException("offset == 0");
+ }
+ return open(offset).readCode();
+ }
+
+ /**
+ * Returns the signature of all but the first 32 bytes of this dex. The
+ * first 32 bytes of dex files are not specified to be included in the
+ * signature.
+ */
+ public byte[] computeSignature() throws IOException {
+ MessageDigest digest;
+ try {
+ digest = MessageDigest.getInstance("SHA-1");
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError();
+ }
+ byte[] buffer = new byte[8192];
+ ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+ data.limit(data.capacity());
+ data.position(SIGNATURE_OFFSET + SIGNATURE_SIZE);
+ while (data.hasRemaining()) {
+ int count = Math.min(buffer.length, data.remaining());
+ data.get(buffer, 0, count);
+ digest.update(buffer, 0, count);
+ }
+ return digest.digest();
+ }
+
+ /**
+ * Returns the checksum of all but the first 12 bytes of {@code dex}.
+ */
+ public int computeChecksum() throws IOException {
+ Adler32 adler32 = new Adler32();
+ byte[] buffer = new byte[8192];
+ ByteBuffer data = this.data.duplicate(); // positioned ByteBuffers aren't thread safe
+ data.limit(data.capacity());
+ data.position(CHECKSUM_OFFSET + CHECKSUM_SIZE);
+ while (data.hasRemaining()) {
+ int count = Math.min(buffer.length, data.remaining());
+ data.get(buffer, 0, count);
+ adler32.update(buffer, 0, count);
+ }
+ return (int) adler32.getValue();
+ }
+
+ /**
+ * Generates the signature and checksum of the dex file {@code out} and
+ * writes them to the file.
+ */
+ public void writeHashes() throws IOException {
+ open(SIGNATURE_OFFSET).write(computeSignature());
+ open(CHECKSUM_OFFSET).writeInt(computeChecksum());
+ }
+
+ public final class Section implements ByteInput, ByteOutput {
+ private final String name;
+ private final ByteBuffer data;
+ private final int initialPosition;
+
+ private Section(String name, ByteBuffer data) {
+ this.name = name;
+ this.data = data;
+ this.initialPosition = data.position();
+ }
+
+ public int getPosition() {
+ return data.position();
+ }
+
+ public int readInt() {
+ return data.getInt();
+ }
+
+ public short readShort() {
+ return data.getShort();
+ }
+
+ public int readUnsignedShort() {
+ return readShort() & 0xffff;
+ }
+
+ public byte readByte() {
+ return data.get();
+ }
+
+ public byte[] readByteArray(int length) {
+ byte[] result = new byte[length];
+ data.get(result);
+ return result;
+ }
+
+ public short[] readShortArray(int length) {
+ short[] result = new short[length];
+ for (int i = 0; i < length; i++) {
+ result[i] = readShort();
+ }
+ return result;
+ }
+
+ public int readUleb128() {
+ return Leb128.readUnsignedLeb128(this);
+ }
+
+ public int readUleb128p1() {
+ return Leb128.readUnsignedLeb128(this) - 1;
+ }
+
+ public int readSleb128() {
+ return Leb128.readSignedLeb128(this);
+ }
+
+ public void writeUleb128p1(int i) {
+ writeUleb128(i + 1);
+ }
+
+ public TypeList readTypeList() {
+ int size = readInt();
+ short[] types = new short[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = readShort();
+ }
+ alignToFourBytes();
+ return new TypeList(Dex.this, types);
+ }
+
+ public String readString() {
+ int offset = readInt();
+ int savedPosition = data.position();
+ int savedLimit = data.limit();
+ data.position(offset);
+ data.limit(data.capacity());
+ try {
+ int expectedLength = readUleb128();
+ String result = Mutf8.decode(this, new char[expectedLength]);
+ if (result.length() != expectedLength) {
+ throw new DexException("Declared length " + expectedLength
+ + " doesn't match decoded length of " + result.length());
+ }
+ return result;
+ } catch (UTFDataFormatException e) {
+ throw new DexException(e);
+ } finally {
+ data.position(savedPosition);
+ data.limit(savedLimit);
+ }
+ }
+
+ public FieldId readFieldId() {
+ int declaringClassIndex = readUnsignedShort();
+ int typeIndex = readUnsignedShort();
+ int nameIndex = readInt();
+ return new FieldId(Dex.this, declaringClassIndex, typeIndex, nameIndex);
+ }
+
+ public MethodId readMethodId() {
+ int declaringClassIndex = readUnsignedShort();
+ int protoIndex = readUnsignedShort();
+ int nameIndex = readInt();
+ return new MethodId(Dex.this, declaringClassIndex, protoIndex, nameIndex);
+ }
+
+ public ProtoId readProtoId() {
+ int shortyIndex = readInt();
+ int returnTypeIndex = readInt();
+ int parametersOffset = readInt();
+ return new ProtoId(Dex.this, shortyIndex, returnTypeIndex, parametersOffset);
+ }
+
+ public ClassDef readClassDef() {
+ int offset = getPosition();
+ int type = readInt();
+ int accessFlags = readInt();
+ int supertype = readInt();
+ int interfacesOffset = readInt();
+ int sourceFileIndex = readInt();
+ int annotationsOffset = readInt();
+ int classDataOffset = readInt();
+ int staticValuesOffset = readInt();
+ return new ClassDef(Dex.this, offset, type, accessFlags, supertype,
+ interfacesOffset, sourceFileIndex, annotationsOffset, classDataOffset,
+ staticValuesOffset);
+ }
+
+ private Code readCode() {
+ int registersSize = readUnsignedShort();
+ int insSize = readUnsignedShort();
+ int outsSize = readUnsignedShort();
+ int triesSize = readUnsignedShort();
+ int debugInfoOffset = readInt();
+ int instructionsSize = readInt();
+ short[] instructions = readShortArray(instructionsSize);
+ Try[] tries;
+ CatchHandler[] catchHandlers;
+ if (triesSize > 0) {
+ 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);
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+ 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);
+ }
+
+ private ClassData readClassData() {
+ int staticFieldsSize = readUleb128();
+ int instanceFieldsSize = readUleb128();
+ int directMethodsSize = readUleb128();
+ int virtualMethodsSize = readUleb128();
+ ClassData.Field[] staticFields = readFields(staticFieldsSize);
+ ClassData.Field[] instanceFields = readFields(instanceFieldsSize);
+ ClassData.Method[] directMethods = readMethods(directMethodsSize);
+ ClassData.Method[] virtualMethods = readMethods(virtualMethodsSize);
+ return new ClassData(staticFields, instanceFields, directMethods, virtualMethods);
+ }
+
+ private ClassData.Field[] readFields(int count) {
+ ClassData.Field[] result = new ClassData.Field[count];
+ int fieldIndex = 0;
+ for (int i = 0; i < count; i++) {
+ fieldIndex += readUleb128(); // field index diff
+ int accessFlags = readUleb128();
+ result[i] = new ClassData.Field(fieldIndex, accessFlags);
+ }
+ return result;
+ }
+
+ private ClassData.Method[] readMethods(int count) {
+ ClassData.Method[] result = new ClassData.Method[count];
+ int methodIndex = 0;
+ for (int i = 0; i < count; i++) {
+ methodIndex += readUleb128(); // method index diff
+ int accessFlags = readUleb128();
+ int codeOff = readUleb128();
+ result[i] = new ClassData.Method(methodIndex, accessFlags, codeOff);
+ }
+ return result;
+ }
+
+ /**
+ * Returns a byte array containing the bytes from {@code start} to this
+ * section's current position.
+ */
+ private byte[] getBytesFrom(int start) {
+ int end = data.position();
+ byte[] result = new byte[end - start];
+ data.position(start);
+ data.get(result);
+ return result;
+ }
+
+ public Annotation readAnnotation() {
+ byte visibility = readByte();
+ int start = data.position();
+ new EncodedValueReader(this, EncodedValueReader.ENCODED_ANNOTATION).skipValue();
+ return new Annotation(Dex.this, visibility, new EncodedValue(getBytesFrom(start)));
+ }
+
+ public EncodedValue readEncodedArray() {
+ int start = data.position();
+ new EncodedValueReader(this, EncodedValueReader.ENCODED_ARRAY).skipValue();
+ return new EncodedValue(getBytesFrom(start));
+ }
+
+ public void skip(int count) {
+ if (count < 0) {
+ throw new IllegalArgumentException();
+ }
+ data.position(data.position() + count);
+ }
+
+ /**
+ * Skips bytes until the position is aligned to a multiple of 4.
+ */
+ public void alignToFourBytes() {
+ data.position((data.position() + 3) & ~3);
+ }
+
+ /**
+ * Writes 0x00 until the position is aligned to a multiple of 4.
+ */
+ public void alignToFourBytesWithZeroFill() {
+ while ((data.position() & 3) != 0) {
+ data.put((byte) 0);
+ }
+ }
+
+ public void assertFourByteAligned() {
+ if ((data.position() & 3) != 0) {
+ throw new IllegalStateException("Not four byte aligned!");
+ }
+ }
+
+ public void write(byte[] bytes) {
+ this.data.put(bytes);
+ }
+
+ public void writeByte(int b) {
+ data.put((byte) b);
+ }
+
+ public void writeShort(short i) {
+ data.putShort(i);
+ }
+
+ public void writeUnsignedShort(int i) {
+ short s = (short) i;
+ if (i != (s & 0xffff)) {
+ throw new IllegalArgumentException("Expected an unsigned short: " + i);
+ }
+ writeShort(s);
+ }
+
+ public void write(short[] shorts) {
+ for (short s : shorts) {
+ writeShort(s);
+ }
+ }
+
+ public void writeInt(int i) {
+ data.putInt(i);
+ }
+
+ public void writeUleb128(int i) {
+ try {
+ Leb128.writeUnsignedLeb128(this, i);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new DexException("Section limit " + data.limit() + " exceeded by " + name);
+ }
+ }
+
+ public void writeSleb128(int i) {
+ try {
+ Leb128.writeSignedLeb128(this, i);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new DexException("Section limit " + data.limit() + " exceeded by " + name);
+ }
+ }
+
+ public void writeStringData(String value) {
+ try {
+ int length = value.length();
+ writeUleb128(length);
+ write(Mutf8.encode(value));
+ writeByte(0);
+ } catch (UTFDataFormatException e) {
+ throw new AssertionError();
+ }
+ }
+
+ public void writeTypeList(TypeList typeList) {
+ short[] types = typeList.getTypes();
+ writeInt(types.length);
+ for (short type : types) {
+ writeShort(type);
+ }
+ alignToFourBytesWithZeroFill();
+ }
+
+ /**
+ * Returns the number of bytes remaining in this section.
+ */
+ public int remaining() {
+ return data.remaining();
+ }
+
+ /**
+ * Returns the number of bytes used by this section.
+ */
+ public int used () {
+ return data.position() - initialPosition;
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/DexException.java b/dex/src/main/java/com/android/dex/DexException.java
new file mode 100644
index 0000000..a30a46f
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/DexException.java
@@ -0,0 +1,33 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ExceptionWithContext;
+
+/**
+ * Thrown when there's a format problem reading, writing, or generally
+ * processing a dex file.
+ */
+public final class DexException extends ExceptionWithContext {
+ public DexException(String message) {
+ super(message);
+ }
+
+ public DexException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/DexFormat.java b/dex/src/main/java/com/android/dex/DexFormat.java
new file mode 100644
index 0000000..85941fd
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/DexFormat.java
@@ -0,0 +1,98 @@
+/*
+ * 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 com.android.dex;
+
+/**
+ * Constants that show up in and are otherwise related to {@code .dex}
+ * files, and helper methods for same.
+ */
+public final class DexFormat {
+ private DexFormat() {}
+
+ /**
+ * API level to target in order to produce the most modern file
+ * format
+ */
+ public static final int API_CURRENT = 14;
+
+ /** API level to target in order to suppress extended opcode usage */
+ public static final int API_NO_EXTENDED_OPCODES = 13;
+
+ /**
+ * file name of the primary {@code .dex} file inside an
+ * application or library {@code .jar} file
+ */
+ public static final String DEX_IN_JAR_NAME = "classes.dex";
+
+ /** common prefix for all dex file "magic numbers" */
+ public static final String MAGIC_PREFIX = "dex\n";
+
+ /** common suffix for all dex file "magic numbers" */
+ public static final String MAGIC_SUFFIX = "\0";
+
+ /** dex file version number for the current format variant */
+ public static final String VERSION_CURRENT = "036";
+
+ /** dex file version number for API level 13 and earlier */
+ public static final String VERSION_FOR_API_13 = "035";
+
+ /**
+ * value used to indicate endianness of file contents
+ */
+ public static final int ENDIAN_TAG = 0x12345678;
+
+ /**
+ * 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.
+ */
+ public static int magicToApi(byte[] magic) {
+ if (magic.length != 8) {
+ return -1;
+ }
+
+ if ((magic[0] != 'd') || (magic[1] != 'e') || (magic[2] != 'x') || (magic[3] != '\n') ||
+ (magic[7] != '\0')) {
+ return -1;
+ }
+
+ String version = "" + ((char) magic[4]) + ((char) magic[5]) +((char) magic[6]);
+
+ if (version.equals(VERSION_CURRENT)) {
+ return API_CURRENT;
+ } else if (version.equals(VERSION_FOR_API_13)) {
+ return 13;
+ }
+
+ return -1;
+ }
+
+ /**
+ * Returns the magic number corresponding to the given target API level.
+ */
+ public static String apiToMagic(int targetApiLevel) {
+ String version;
+
+ if (targetApiLevel >= API_CURRENT) {
+ version = VERSION_CURRENT;
+ } else {
+ version = VERSION_FOR_API_13;
+ }
+
+ return MAGIC_PREFIX + version + MAGIC_SUFFIX;
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValue.java b/dex/src/main/java/com/android/dex/EncodedValue.java
new file mode 100644
index 0000000..8d0c3ad
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValue.java
@@ -0,0 +1,57 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteArrayByteInput;
+import com.android.dex.util.ByteInput;
+
+/**
+ * An encoded value or array.
+ */
+public final class EncodedValue implements Comparable<EncodedValue> {
+ private final byte[] data;
+
+ public EncodedValue(byte[] data) {
+ this.data = data;
+ }
+
+ public ByteInput asByteInput() {
+ return new ByteArrayByteInput(data);
+ }
+
+ public byte[] getBytes() {
+ return data;
+ }
+
+ public void writeTo(Dex.Section out) {
+ out.write(data);
+ }
+
+ @Override public int compareTo(EncodedValue other) {
+ int size = Math.min(data.length, other.data.length);
+ for (int i = 0; i < size; i++) {
+ if (data[i] != other.data[i]) {
+ return (data[i] & 0xff) - (other.data[i] & 0xff);
+ }
+ }
+ return data.length - other.data.length;
+ }
+
+ @Override public String toString() {
+ return Integer.toHexString(data[0] & 0xff) + "...(" + data.length + ")";
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValueCodec.java b/dex/src/main/java/com/android/dex/EncodedValueCodec.java
new file mode 100644
index 0000000..7fc1724
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValueCodec.java
@@ -0,0 +1,187 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+
+/**
+ * Read and write {@code encoded_value} primitives.
+ */
+public final class EncodedValueCodec {
+ private EncodedValueCodec() {
+ }
+
+ /**
+ * Writes a signed integral to {@code out}.
+ */
+ public static void writeSignedIntegralValue(ByteOutput out, int type, long value) {
+ /*
+ * Figure out how many bits are needed to represent the value,
+ * including a sign bit: The bit count is subtracted from 65
+ * and not 64 to account for the sign bit. The xor operation
+ * has the effect of leaving non-negative values alone and
+ * unary complementing negative values (so that a leading zero
+ * count always returns a useful number for our present
+ * purpose).
+ */
+ int requiredBits = 65 - Long.numberOfLeadingZeros(value ^ (value >> 63));
+
+ // Round up the requiredBits to a number of bytes.
+ int requiredBytes = (requiredBits + 0x07) >> 3;
+
+ /*
+ * Write the header byte, which includes the type and
+ * requiredBytes - 1.
+ */
+ out.writeByte(type | ((requiredBytes - 1) << 5));
+
+ // Write the value, per se.
+ while (requiredBytes > 0) {
+ out.writeByte((byte) value);
+ value >>= 8;
+ requiredBytes--;
+ }
+ }
+
+ /**
+ * Writes an unsigned integral to {@code out}.
+ */
+ public static void writeUnsignedIntegralValue(ByteOutput out, int type, long value) {
+ // Figure out how many bits are needed to represent the value.
+ int requiredBits = 64 - Long.numberOfLeadingZeros(value);
+ if (requiredBits == 0) {
+ requiredBits = 1;
+ }
+
+ // Round up the requiredBits to a number of bytes.
+ int requiredBytes = (requiredBits + 0x07) >> 3;
+
+ /*
+ * Write the header byte, which includes the type and
+ * requiredBytes - 1.
+ */
+ out.writeByte(type | ((requiredBytes - 1) << 5));
+
+ // Write the value, per se.
+ while (requiredBytes > 0) {
+ out.writeByte((byte) value);
+ value >>= 8;
+ requiredBytes--;
+ }
+ }
+
+ /**
+ * Writes a right-zero-extended value to {@code out}.
+ */
+ public static void writeRightZeroExtendedValue(ByteOutput out, int type, long value) {
+ // Figure out how many bits are needed to represent the value.
+ int requiredBits = 64 - Long.numberOfTrailingZeros(value);
+ if (requiredBits == 0) {
+ requiredBits = 1;
+ }
+
+ // Round up the requiredBits to a number of bytes.
+ int requiredBytes = (requiredBits + 0x07) >> 3;
+
+ // Scootch the first bits to be written down to the low-order bits.
+ value >>= 64 - (requiredBytes * 8);
+
+ /*
+ * Write the header byte, which includes the type and
+ * requiredBytes - 1.
+ */
+ out.writeByte(type | ((requiredBytes - 1) << 5));
+
+ // Write the value, per se.
+ while (requiredBytes > 0) {
+ out.writeByte((byte) value);
+ value >>= 8;
+ requiredBytes--;
+ }
+ }
+
+ /**
+ * Read a signed integer.
+ *
+ * @param zwidth byte count minus one
+ */
+ public static int readSignedInt(ByteInput in, int zwidth) {
+ int result = 0;
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+ }
+ result >>= (3 - zwidth) * 8;
+ return result;
+ }
+
+ /**
+ * Read an unsigned integer.
+ *
+ * @param zwidth byte count minus one
+ * @param fillOnRight true to zero fill on the right; false on the left
+ */
+ public static int readUnsignedInt(ByteInput in, int zwidth, boolean fillOnRight) {
+ int result = 0;
+ if (!fillOnRight) {
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+ }
+ result >>>= (3 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xff) << 24);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Read a signed long.
+ *
+ * @param zwidth byte count minus one
+ */
+ public static long readSignedLong(ByteInput in, int zwidth) {
+ long result = 0;
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+ }
+ result >>= (7 - zwidth) * 8;
+ return result;
+ }
+
+ /**
+ * Read an unsigned long.
+ *
+ * @param zwidth byte count minus one
+ * @param fillOnRight true to zero fill on the right; false on the left
+ */
+ public static long readUnsignedLong(ByteInput in, int zwidth, boolean fillOnRight) {
+ long result = 0;
+ if (!fillOnRight) {
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+ }
+ result >>>= (7 - zwidth) * 8;
+ } else {
+ for (int i = zwidth; i >= 0; i--) {
+ result = (result >>> 8) | ((in.readByte() & 0xffL) << 56);
+ }
+ }
+ return result;
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/EncodedValueReader.java b/dex/src/main/java/com/android/dex/EncodedValueReader.java
new file mode 100644
index 0000000..6f60538
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/EncodedValueReader.java
@@ -0,0 +1,287 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+
+/**
+ * Pull parser for encoded values.
+ */
+public final class EncodedValueReader {
+ public static final int ENCODED_BYTE = 0x00;
+ public static final int ENCODED_SHORT = 0x02;
+ public static final int ENCODED_CHAR = 0x03;
+ public static final int ENCODED_INT = 0x04;
+ public static final int ENCODED_LONG = 0x06;
+ public static final int ENCODED_FLOAT = 0x10;
+ public static final int ENCODED_DOUBLE = 0x11;
+ public static final int ENCODED_STRING = 0x17;
+ public static final int ENCODED_TYPE = 0x18;
+ public static final int ENCODED_FIELD = 0x19;
+ public static final int ENCODED_ENUM = 0x1b;
+ public static final int ENCODED_METHOD = 0x1a;
+ public static final int ENCODED_ARRAY = 0x1c;
+ public static final int ENCODED_ANNOTATION = 0x1d;
+ public static final int ENCODED_NULL = 0x1e;
+ public static final int ENCODED_BOOLEAN = 0x1f;
+
+ /** placeholder type if the type is not yet known */
+ private static final int MUST_READ = -1;
+
+ protected final ByteInput in;
+ private int type = MUST_READ;
+ private int annotationType;
+ private int arg;
+
+ public EncodedValueReader(ByteInput in) {
+ this.in = in;
+ }
+
+ public EncodedValueReader(EncodedValue in) {
+ this(in.asByteInput());
+ }
+
+ /**
+ * Creates a new encoded value reader whose only value is the specified
+ * known type. This is useful for encoded values without a type prefix,
+ * such as class_def_item's encoded_array or annotation_item's
+ * encoded_annotation.
+ */
+ public EncodedValueReader(ByteInput in, int knownType) {
+ this.in = in;
+ this.type = knownType;
+ }
+
+ public EncodedValueReader(EncodedValue in, int knownType) {
+ this(in.asByteInput(), knownType);
+ }
+
+ /**
+ * Returns the type of the next value to read.
+ */
+ public int peek() {
+ if (type == MUST_READ) {
+ int argAndType = in.readByte() & 0xff;
+ type = argAndType & 0x1f;
+ arg = (argAndType & 0xe0) >> 5;
+ }
+ return type;
+ }
+
+ /**
+ * Begins reading the elements of an array, returning the array's size. The
+ * caller must follow up by calling a read method for each element in the
+ * array. For example, this reads a byte array: <pre> {@code
+ * int arraySize = readArray();
+ * for (int i = 0, i < arraySize; i++) {
+ * readByte();
+ * }
+ * }</pre>
+ */
+ public int readArray() {
+ checkType(ENCODED_ARRAY);
+ type = MUST_READ;
+ return Leb128.readUnsignedLeb128(in);
+ }
+
+ /**
+ * Begins reading the fields of an annotation, returning the number of
+ * fields. The caller must follow up by making alternating calls to {@link
+ * #readAnnotationName()} and another read method. For example, this reads
+ * an annotation whose fields are all bytes: <pre> {@code
+ * int fieldCount = readAnnotation();
+ * int annotationType = getAnnotationType();
+ * for (int i = 0; i < fieldCount; i++) {
+ * readAnnotationName();
+ * readByte();
+ * }
+ * }</pre>
+ */
+ public int readAnnotation() {
+ checkType(ENCODED_ANNOTATION);
+ type = MUST_READ;
+ annotationType = Leb128.readUnsignedLeb128(in);
+ return Leb128.readUnsignedLeb128(in);
+ }
+
+ /**
+ * Returns the type of the annotation just returned by {@link
+ * #readAnnotation()}. This method's value is undefined unless the most
+ * recent call was to {@link #readAnnotation()}.
+ */
+ public int getAnnotationType() {
+ return annotationType;
+ }
+
+ public int readAnnotationName() {
+ return Leb128.readUnsignedLeb128(in);
+ }
+
+ public byte readByte() {
+ checkType(ENCODED_BYTE);
+ type = MUST_READ;
+ return (byte) EncodedValueCodec.readSignedInt(in, arg);
+ }
+
+ public short readShort() {
+ checkType(ENCODED_SHORT);
+ type = MUST_READ;
+ return (short) EncodedValueCodec.readSignedInt(in, arg);
+ }
+
+ public char readChar() {
+ checkType(ENCODED_CHAR);
+ type = MUST_READ;
+ return (char) EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public int readInt() {
+ checkType(ENCODED_INT);
+ type = MUST_READ;
+ return EncodedValueCodec.readSignedInt(in, arg);
+ }
+
+ public long readLong() {
+ checkType(ENCODED_LONG);
+ type = MUST_READ;
+ return EncodedValueCodec.readSignedLong(in, arg);
+ }
+
+ public float readFloat() {
+ checkType(ENCODED_FLOAT);
+ type = MUST_READ;
+ return Float.intBitsToFloat(EncodedValueCodec.readUnsignedInt(in, arg, true));
+ }
+
+ public double readDouble() {
+ checkType(ENCODED_DOUBLE);
+ type = MUST_READ;
+ return Double.longBitsToDouble(EncodedValueCodec.readUnsignedLong(in, arg, true));
+ }
+
+ public int readString() {
+ checkType(ENCODED_STRING);
+ type = MUST_READ;
+ return EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public int readType() {
+ checkType(ENCODED_TYPE);
+ type = MUST_READ;
+ return EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public int readField() {
+ checkType(ENCODED_FIELD);
+ type = MUST_READ;
+ return EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public int readEnum() {
+ checkType(ENCODED_ENUM);
+ type = MUST_READ;
+ return EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public int readMethod() {
+ checkType(ENCODED_METHOD);
+ type = MUST_READ;
+ return EncodedValueCodec.readUnsignedInt(in, arg, false);
+ }
+
+ public void readNull() {
+ checkType(ENCODED_NULL);
+ type = MUST_READ;
+ }
+
+ public boolean readBoolean() {
+ checkType(ENCODED_BOOLEAN);
+ type = MUST_READ;
+ return arg != 0;
+ }
+
+ /**
+ * Skips a single value, including its nested values if it is an array or
+ * annotation.
+ */
+ public void skipValue() {
+ switch (peek()) {
+ case ENCODED_BYTE:
+ readByte();
+ break;
+ case ENCODED_SHORT:
+ readShort();
+ break;
+ case ENCODED_CHAR:
+ readChar();
+ break;
+ case ENCODED_INT:
+ readInt();
+ break;
+ case ENCODED_LONG:
+ readLong();
+ break;
+ case ENCODED_FLOAT:
+ readFloat();
+ break;
+ case ENCODED_DOUBLE:
+ readDouble();
+ break;
+ case ENCODED_STRING:
+ readString();
+ break;
+ case ENCODED_TYPE:
+ readType();
+ break;
+ case ENCODED_FIELD:
+ readField();
+ break;
+ case ENCODED_ENUM:
+ readEnum();
+ break;
+ case ENCODED_METHOD:
+ readMethod();
+ break;
+ case ENCODED_ARRAY:
+ for (int i = 0, size = readArray(); i < size; i++) {
+ skipValue();
+ }
+ break;
+ case ENCODED_ANNOTATION:
+ for (int i = 0, size = readAnnotation(); i < size; i++) {
+ readAnnotationName();
+ skipValue();
+ }
+ break;
+ case ENCODED_NULL:
+ readNull();
+ break;
+ case ENCODED_BOOLEAN:
+ readBoolean();
+ break;
+ default:
+ throw new DexException("Unexpected type: " + Integer.toHexString(type));
+ }
+ }
+
+ private void checkType(int expected) {
+ if (peek() != expected) {
+ throw new IllegalStateException(
+ String.format("Expected %x but was %x", expected, peek()));
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/FieldId.java b/dex/src/main/java/com/android/dex/FieldId.java
new file mode 100644
index 0000000..2f41708
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/FieldId.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class FieldId implements Comparable<FieldId> {
+ private final Dex dex;
+ private final int declaringClassIndex;
+ private final int typeIndex;
+ private final int nameIndex;
+
+ public FieldId(Dex dex, int declaringClassIndex, int typeIndex, int nameIndex) {
+ this.dex = dex;
+ this.declaringClassIndex = declaringClassIndex;
+ this.typeIndex = typeIndex;
+ this.nameIndex = nameIndex;
+ }
+
+ public int getDeclaringClassIndex() {
+ return declaringClassIndex;
+ }
+
+ public int getTypeIndex() {
+ return typeIndex;
+ }
+
+ public int getNameIndex() {
+ return nameIndex;
+ }
+
+ public int compareTo(FieldId other) {
+ if (declaringClassIndex != other.declaringClassIndex) {
+ return Unsigned.compare(declaringClassIndex, other.declaringClassIndex);
+ }
+ if (nameIndex != other.nameIndex) {
+ return Unsigned.compare(nameIndex, other.nameIndex);
+ }
+ return Unsigned.compare(typeIndex, other.typeIndex); // should always be 0
+ }
+
+ public void writeTo(Dex.Section out) {
+ out.writeUnsignedShort(declaringClassIndex);
+ out.writeUnsignedShort(typeIndex);
+ out.writeInt(nameIndex);
+ }
+
+ @Override public String toString() {
+ if (dex == null) {
+ return declaringClassIndex + " " + typeIndex + " " + nameIndex;
+ }
+ return dex.typeNames().get(typeIndex) + "." + dex.strings().get(nameIndex);
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/Leb128.java b/dex/src/main/java/com/android/dex/Leb128.java
new file mode 100644
index 0000000..1a82e38
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Leb128.java
@@ -0,0 +1,161 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import com.android.dex.util.ByteOutput;
+
+/**
+ * Reads and writes DWARFv3 LEB 128 signed and unsigned integers. See DWARF v3
+ * section 7.6.
+ */
+public final class Leb128 {
+ private Leb128() {
+ }
+
+ /**
+ * Gets the number of bytes in the unsigned LEB128 encoding of the
+ * given value.
+ *
+ * @param value the value in question
+ * @return its write size, in bytes
+ */
+ public static int unsignedLeb128Size(int value) {
+ // TODO: This could be much cleverer.
+
+ int remaining = value >> 7;
+ int count = 0;
+
+ while (remaining != 0) {
+ remaining >>= 7;
+ count++;
+ }
+
+ return count + 1;
+ }
+
+ /**
+ * Gets the number of bytes in the signed LEB128 encoding of the
+ * given value.
+ *
+ * @param value the value in question
+ * @return its write size, in bytes
+ */
+ public static int signedLeb128Size(int value) {
+ // TODO: This could be much cleverer.
+
+ int remaining = value >> 7;
+ int count = 0;
+ boolean hasMore = true;
+ int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
+
+ while (hasMore) {
+ hasMore = (remaining != end)
+ || ((remaining & 1) != ((value >> 6) & 1));
+
+ value = remaining;
+ remaining >>= 7;
+ count++;
+ }
+
+ return count;
+ }
+
+ /**
+ * Reads an signed integer from {@code in}.
+ */
+ public static int readSignedLeb128(ByteInput in) {
+ int result = 0;
+ int cur;
+ int count = 0;
+ int signBits = -1;
+
+ do {
+ cur = in.readByte() & 0xff;
+ result |= (cur & 0x7f) << (count * 7);
+ signBits <<= 7;
+ count++;
+ } while (((cur & 0x80) == 0x80) && count < 5);
+
+ if ((cur & 0x80) == 0x80) {
+ throw new DexException("invalid LEB128 sequence");
+ }
+
+ // Sign extend if appropriate
+ if (((signBits >> 1) & result) != 0 ) {
+ result |= signBits;
+ }
+
+ return result;
+ }
+
+ /**
+ * Reads an unsigned integer from {@code in}.
+ */
+ public static int readUnsignedLeb128(ByteInput in) {
+ int result = 0;
+ int cur;
+ int count = 0;
+
+ do {
+ cur = in.readByte() & 0xff;
+ result |= (cur & 0x7f) << (count * 7);
+ count++;
+ } while (((cur & 0x80) == 0x80) && count < 5);
+
+ if ((cur & 0x80) == 0x80) {
+ throw new DexException("invalid LEB128 sequence");
+ }
+
+ return result;
+ }
+
+ /**
+ * Writes {@code value} as an unsigned integer to {@code out}, starting at
+ * {@code offset}. Returns the number of bytes written.
+ */
+ public static void writeUnsignedLeb128(ByteOutput out, int value) {
+ int remaining = value >>> 7;
+
+ while (remaining != 0) {
+ out.writeByte((byte) ((value & 0x7f) | 0x80));
+ value = remaining;
+ remaining >>>= 7;
+ }
+
+ out.writeByte((byte) (value & 0x7f));
+ }
+
+ /**
+ * Writes {@code value} as a signed integer to {@code out}, starting at
+ * {@code offset}. Returns the number of bytes written.
+ */
+ public static void writeSignedLeb128(ByteOutput out, int value) {
+ int remaining = value >> 7;
+ boolean hasMore = true;
+ int end = ((value & Integer.MIN_VALUE) == 0) ? 0 : -1;
+
+ while (hasMore) {
+ hasMore = (remaining != end)
+ || ((remaining & 1) != ((value >> 6) & 1));
+
+ out.writeByte((byte) ((value & 0x7f) | (hasMore ? 0x80 : 0)));
+ value = remaining;
+ remaining >>= 7;
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/MethodId.java b/dex/src/main/java/com/android/dex/MethodId.java
new file mode 100644
index 0000000..e518740
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/MethodId.java
@@ -0,0 +1,70 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class MethodId implements Comparable<MethodId> {
+ private final Dex dex;
+ private final int declaringClassIndex;
+ private final int protoIndex;
+ private final int nameIndex;
+
+ public MethodId(Dex dex, int declaringClassIndex, int protoIndex, int nameIndex) {
+ this.dex = dex;
+ this.declaringClassIndex = declaringClassIndex;
+ this.protoIndex = protoIndex;
+ this.nameIndex = nameIndex;
+ }
+
+ public int getDeclaringClassIndex() {
+ return declaringClassIndex;
+ }
+
+ public int getProtoIndex() {
+ return protoIndex;
+ }
+
+ public int getNameIndex() {
+ return nameIndex;
+ }
+
+ public int compareTo(MethodId other) {
+ if (declaringClassIndex != other.declaringClassIndex) {
+ return Unsigned.compare(declaringClassIndex, other.declaringClassIndex);
+ }
+ if (nameIndex != other.nameIndex) {
+ return Unsigned.compare(nameIndex, other.nameIndex);
+ }
+ return Unsigned.compare(protoIndex, other.protoIndex);
+ }
+
+ public void writeTo(Dex.Section out) {
+ out.writeUnsignedShort(declaringClassIndex);
+ out.writeUnsignedShort(protoIndex);
+ out.writeInt(nameIndex);
+ }
+
+ @Override public String toString() {
+ if (dex == null) {
+ return declaringClassIndex + " " + protoIndex + " " + nameIndex;
+ }
+ return dex.typeNames().get(declaringClassIndex)
+ + "." + dex.strings().get(nameIndex)
+ + dex.readTypeList(dex.protoIds().get(protoIndex).getParametersOffset());
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/Mutf8.java b/dex/src/main/java/com/android/dex/Mutf8.java
new file mode 100644
index 0000000..c64da33
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/Mutf8.java
@@ -0,0 +1,115 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteInput;
+import java.io.UTFDataFormatException;
+
+/**
+ * Modified UTF-8 as described in the dex file format spec.
+ *
+ * <p>Derived from libcore's MUTF-8 encoder at java.nio.charset.ModifiedUtf8.
+ */
+public final class Mutf8 {
+ private Mutf8() {}
+
+ /**
+ * Decodes bytes from {@code in} into {@code out} until a delimiter 0x00 is
+ * encountered. Returns a new string containing the decoded characters.
+ */
+ public static String decode(ByteInput in, char[] out) throws UTFDataFormatException {
+ int s = 0;
+ while (true) {
+ char a = (char) (in.readByte() & 0xff);
+ if (a == 0) {
+ return new String(out, 0, s);
+ }
+ out[s] = a;
+ if (a < '\u0080') {
+ s++;
+ } else if ((a & 0xe0) == 0xc0) {
+ int b = in.readByte() & 0xff;
+ if ((b & 0xC0) != 0x80) {
+ throw new UTFDataFormatException("bad second byte");
+ }
+ out[s++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+ } else if ((a & 0xf0) == 0xe0) {
+ int b = in.readByte() & 0xff;
+ int c = in.readByte() & 0xff;
+ if (((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80)) {
+ throw new UTFDataFormatException("bad second or third byte");
+ }
+ out[s++] = (char) (((a & 0x0F) << 12) | ((b & 0x3F) << 6) | (c & 0x3F));
+ } else {
+ throw new UTFDataFormatException("bad byte");
+ }
+ }
+ }
+
+ /**
+ * Returns the number of bytes the modified UTF8 representation of 's' would take.
+ */
+ private static long countBytes(String s, boolean shortLength) throws UTFDataFormatException {
+ long result = 0;
+ final int length = s.length();
+ for (int i = 0; i < length; ++i) {
+ char ch = s.charAt(i);
+ if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+ ++result;
+ } else if (ch <= 2047) {
+ result += 2;
+ } else {
+ result += 3;
+ }
+ if (shortLength && result > 65535) {
+ throw new UTFDataFormatException("String more than 65535 UTF bytes long");
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Encodes the modified UTF-8 bytes corresponding to {@code s} into {@code
+ * dst}, starting at {@code offset}.
+ */
+ public static void encode(byte[] dst, int offset, String s) {
+ final int length = s.length();
+ for (int i = 0; i < length; i++) {
+ char ch = s.charAt(i);
+ if (ch != 0 && ch <= 127) { // U+0000 uses two bytes.
+ dst[offset++] = (byte) ch;
+ } else if (ch <= 2047) {
+ dst[offset++] = (byte) (0xc0 | (0x1f & (ch >> 6)));
+ dst[offset++] = (byte) (0x80 | (0x3f & ch));
+ } else {
+ dst[offset++] = (byte) (0xe0 | (0x0f & (ch >> 12)));
+ dst[offset++] = (byte) (0x80 | (0x3f & (ch >> 6)));
+ dst[offset++] = (byte) (0x80 | (0x3f & ch));
+ }
+ }
+ }
+
+ /**
+ * Returns an array containing the <i>modified UTF-8</i> form of {@code s}.
+ */
+ public static byte[] encode(String s) throws UTFDataFormatException {
+ int utfCount = (int) countBytes(s, true);
+ byte[] result = new byte[utfCount];
+ encode(result, 0, s);
+ return result;
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/ProtoId.java b/dex/src/main/java/com/android/dex/ProtoId.java
new file mode 100644
index 0000000..9d9f484
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/ProtoId.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class ProtoId implements Comparable<ProtoId> {
+ private final Dex dex;
+ private final int shortyIndex;
+ private final int returnTypeIndex;
+ private final int parametersOffset;
+
+ public ProtoId(Dex dex, int shortyIndex, int returnTypeIndex, int parametersOffset) {
+ this.dex = dex;
+ this.shortyIndex = shortyIndex;
+ this.returnTypeIndex = returnTypeIndex;
+ this.parametersOffset = parametersOffset;
+ }
+
+ public int compareTo(ProtoId other) {
+ if (returnTypeIndex != other.returnTypeIndex) {
+ return Unsigned.compare(returnTypeIndex, other.returnTypeIndex);
+ }
+ return Unsigned.compare(parametersOffset, other.parametersOffset);
+ }
+
+ public int getShortyIndex() {
+ return shortyIndex;
+ }
+
+ public int getReturnTypeIndex() {
+ return returnTypeIndex;
+ }
+
+ public int getParametersOffset() {
+ return parametersOffset;
+ }
+
+ public void writeTo(Dex.Section out) {
+ out.writeInt(shortyIndex);
+ out.writeInt(returnTypeIndex);
+ out.writeInt(parametersOffset);
+ }
+
+ @Override public String toString() {
+ if (dex == null) {
+ return shortyIndex + " " + returnTypeIndex + " " + parametersOffset;
+ }
+
+ return dex.strings().get(shortyIndex)
+ + ": " + dex.typeNames().get(returnTypeIndex)
+ + " " + dex.readTypeList(parametersOffset);
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/SizeOf.java b/dex/src/main/java/com/android/dex/SizeOf.java
new file mode 100644
index 0000000..65fab56
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/SizeOf.java
@@ -0,0 +1,110 @@
+/*
+ * 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 com.android.dex;
+
+public final class SizeOf {
+ private SizeOf() {}
+
+ public static final int UBYTE = 1;
+ public static final int USHORT = 2;
+ public static final int UINT = 4;
+
+ public static final int SIGNATURE = UBYTE * 20;
+
+ /**
+ * magic ubyte[8]
+ * checksum uint
+ * signature ubyte[20]
+ * file_size uint
+ * header_size uint
+ * endian_tag uint
+ * link_size uint
+ * link_off uint
+ * map_off uint
+ * string_ids_size uint
+ * string_ids_off uint
+ * type_ids_size uint
+ * type_ids_off uint
+ * proto_ids_size uint
+ * proto_ids_off uint
+ * field_ids_size uint
+ * field_ids_off uint
+ * method_ids_size uint
+ * method_ids_off uint
+ * class_defs_size uint
+ * class_defs_off uint
+ * data_size uint
+ * data_off uint
+ */
+ public static final int HEADER_ITEM = (8 * UBYTE) + UINT + SIGNATURE + (20 * UINT); // 0x70
+
+ /**
+ * string_data_off uint
+ */
+ public static final int STRING_ID_ITEM = UINT;
+
+ /**
+ * descriptor_idx uint
+ */
+ public static final int TYPE_ID_ITEM = UINT;
+
+ /**
+ * type_idx ushort
+ */
+ public static final int TYPE_ITEM = USHORT;
+
+ /**
+ * shorty_idx uint
+ * return_type_idx uint
+ * return_type_idx uint
+ */
+ public static final int PROTO_ID_ITEM = UINT + UINT + UINT;
+
+ /**
+ * class_idx ushort
+ * type_idx/proto_idx ushort
+ * name_idx uint
+ */
+ public static final int MEMBER_ID_ITEM = USHORT + USHORT + UINT;
+
+ /**
+ * class_idx uint
+ * access_flags uint
+ * superclass_idx uint
+ * interfaces_off uint
+ * source_file_idx uint
+ * annotations_off uint
+ * class_data_off uint
+ * static_values_off uint
+ */
+ public static final int CLASS_DEF_ITEM = 8 * UINT;
+
+ /**
+ * type ushort
+ * unused ushort
+ * size uint
+ * offset uint
+ */
+ public static final int MAP_ITEM = USHORT + USHORT + UINT + UINT;
+
+ /**
+ * start_addr uint
+ * insn_count ushort
+ * handler_off ushort
+ */
+ public static final int TRY_ITEM = UINT + USHORT + USHORT;
+}
diff --git a/dex/src/main/java/com/android/dex/TableOfContents.java b/dex/src/main/java/com/android/dex/TableOfContents.java
new file mode 100644
index 0000000..d1b87ac
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/TableOfContents.java
@@ -0,0 +1,236 @@
+/*
+ * 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 com.android.dex;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+/**
+ * The file header and map.
+ */
+public final class TableOfContents {
+
+ /*
+ * TODO: factor out ID constants.
+ */
+
+ public final Section header = new Section(0x0000);
+ public final Section stringIds = new Section(0x0001);
+ public final Section typeIds = new Section(0x0002);
+ public final Section protoIds = new Section(0x0003);
+ public final Section fieldIds = new Section(0x0004);
+ public final Section methodIds = new Section(0x0005);
+ public final Section classDefs = new Section(0x0006);
+ public final Section mapList = new Section(0x1000);
+ public final Section typeLists = new Section(0x1001);
+ public final Section annotationSetRefLists = new Section(0x1002);
+ public final Section annotationSets = new Section(0x1003);
+ public final Section classDatas = new Section(0x2000);
+ public final Section codes = new Section(0x2001);
+ public final Section stringDatas = new Section(0x2002);
+ public final Section debugInfos = new Section(0x2003);
+ public final Section annotations = new Section(0x2004);
+ public final Section encodedArrays = new Section(0x2005);
+ public final Section annotationsDirectories = new Section(0x2006);
+ public final Section[] sections = {
+ header, stringIds, typeIds, protoIds, fieldIds, methodIds, classDefs, mapList,
+ typeLists, annotationSetRefLists, annotationSets, classDatas, codes, stringDatas,
+ debugInfos, annotations, encodedArrays, annotationsDirectories
+ };
+
+ public int checksum;
+ public byte[] signature;
+ public int fileSize;
+ public int linkSize;
+ public int linkOff;
+ public int dataSize;
+ public int dataOff;
+
+ public TableOfContents() {
+ signature = new byte[20];
+ }
+
+ public void readFrom(Dex dex) throws IOException {
+ readHeader(dex.open(0));
+ readMap(dex.open(mapList.off));
+ computeSizesFromOffsets();
+ }
+
+ private void readHeader(Dex.Section headerIn) throws UnsupportedEncodingException {
+ byte[] magic = headerIn.readByteArray(8);
+ int apiTarget = DexFormat.magicToApi(magic);
+
+ if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) {
+ throw new DexException("Unexpected magic: " + Arrays.toString(magic));
+ }
+
+ checksum = headerIn.readInt();
+ signature = headerIn.readByteArray(20);
+ fileSize = headerIn.readInt();
+ int headerSize = headerIn.readInt();
+ if (headerSize != SizeOf.HEADER_ITEM) {
+ throw new DexException("Unexpected header: 0x" + Integer.toHexString(headerSize));
+ }
+ int endianTag = headerIn.readInt();
+ if (endianTag != DexFormat.ENDIAN_TAG) {
+ throw new DexException("Unexpected endian tag: 0x" + Integer.toHexString(endianTag));
+ }
+ linkSize = headerIn.readInt();
+ linkOff = headerIn.readInt();
+ mapList.off = headerIn.readInt();
+ if (mapList.off == 0) {
+ throw new DexException("Cannot merge dex files that do not contain a map");
+ }
+ stringIds.size = headerIn.readInt();
+ stringIds.off = headerIn.readInt();
+ typeIds.size = headerIn.readInt();
+ typeIds.off = headerIn.readInt();
+ protoIds.size = headerIn.readInt();
+ protoIds.off = headerIn.readInt();
+ fieldIds.size = headerIn.readInt();
+ fieldIds.off = headerIn.readInt();
+ methodIds.size = headerIn.readInt();
+ methodIds.off = headerIn.readInt();
+ classDefs.size = headerIn.readInt();
+ classDefs.off = headerIn.readInt();
+ dataSize = headerIn.readInt();
+ dataOff = headerIn.readInt();
+ }
+
+ private void readMap(Dex.Section in) throws IOException {
+ int mapSize = in.readInt();
+ Section previous = null;
+ for (int i = 0; i < mapSize; i++) {
+ short type = in.readShort();
+ in.readShort(); // unused
+ Section section = getSection(type);
+ int size = in.readInt();
+ int offset = in.readInt();
+
+ if ((section.size != 0 && section.size != size)
+ || (section.off != -1 && section.off != offset)) {
+ throw new DexException("Unexpected map value for 0x" + Integer.toHexString(type));
+ }
+
+ section.size = size;
+ section.off = offset;
+
+ if (previous != null && previous.off > section.off) {
+ throw new DexException("Map is unsorted at " + previous + ", " + section);
+ }
+
+ previous = section;
+ }
+ Arrays.sort(sections);
+ }
+
+ public void computeSizesFromOffsets() {
+ int end = dataOff + dataSize;
+ for (int i = sections.length - 1; i >= 0; i--) {
+ Section section = sections[i];
+ if (section.off == -1) {
+ continue;
+ }
+ if (section.off > end) {
+ throw new DexException("Map is unsorted at " + section);
+ }
+ section.byteCount = end - section.off;
+ end = section.off;
+ }
+ }
+
+ private Section getSection(short type) {
+ for (Section section : sections) {
+ if (section.type == type) {
+ return section;
+ }
+ }
+ throw new IllegalArgumentException("No such map item: " + type);
+ }
+
+ public void writeHeader(Dex.Section out) throws IOException {
+ out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8"));
+ out.writeInt(checksum);
+ out.write(signature);
+ out.writeInt(fileSize);
+ out.writeInt(SizeOf.HEADER_ITEM);
+ out.writeInt(DexFormat.ENDIAN_TAG);
+ out.writeInt(linkSize);
+ out.writeInt(linkOff);
+ out.writeInt(mapList.off);
+ out.writeInt(stringIds.size);
+ out.writeInt(stringIds.off);
+ out.writeInt(typeIds.size);
+ out.writeInt(typeIds.off);
+ out.writeInt(protoIds.size);
+ out.writeInt(protoIds.off);
+ out.writeInt(fieldIds.size);
+ out.writeInt(fieldIds.off);
+ out.writeInt(methodIds.size);
+ out.writeInt(methodIds.off);
+ out.writeInt(classDefs.size);
+ out.writeInt(classDefs.off);
+ out.writeInt(dataSize);
+ out.writeInt(dataOff);
+ }
+
+ public void writeMap(Dex.Section out) throws IOException {
+ int count = 0;
+ for (Section section : sections) {
+ if (section.exists()) {
+ count++;
+ }
+ }
+
+ out.writeInt(count);
+ for (Section section : sections) {
+ if (section.exists()) {
+ out.writeShort(section.type);
+ out.writeShort((short) 0);
+ out.writeInt(section.size);
+ out.writeInt(section.off);
+ }
+ }
+ }
+
+ public static class Section implements Comparable<Section> {
+ public final short type;
+ public int size = 0;
+ public int off = -1;
+ public int byteCount = 0;
+
+ public Section(int type) {
+ this.type = (short) type;
+ }
+
+ public boolean exists() {
+ return size > 0;
+ }
+
+ public int compareTo(Section section) {
+ if (off != section.off) {
+ return off < section.off ? -1 : 1;
+ }
+ return 0;
+ }
+
+ @Override public String toString() {
+ return String.format("Section[type=%#x,off=%#x,size=%#x]", type, off, size);
+ }
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/TypeList.java b/dex/src/main/java/com/android/dex/TypeList.java
new file mode 100644
index 0000000..6e321fb
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/TypeList.java
@@ -0,0 +1,55 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.Unsigned;
+
+public final class TypeList implements Comparable<TypeList> {
+
+ public static final TypeList EMPTY = new TypeList(null, new short[0]);
+
+ private final Dex dex;
+ private final short[] types;
+
+ public TypeList(Dex dex, short[] types) {
+ this.dex = dex;
+ this.types = types;
+ }
+
+ public short[] getTypes() {
+ return types;
+ }
+
+ @Override public int compareTo(TypeList other) {
+ for (int i = 0; i < types.length && i < other.types.length; i++) {
+ if (types[i] != other.types[i]) {
+ return Unsigned.compare(types[i], other.types[i]);
+ }
+ }
+ return Unsigned.compare(types.length, other.types.length);
+ }
+
+ @Override public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append("(");
+ for (int i = 0, typesLength = types.length; i < typesLength; i++) {
+ result.append(dex != null ? dex.typeNames().get(types[i]) : types[i]);
+ }
+ result.append(")");
+ return result.toString();
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java b/dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
similarity index 61%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
copy to dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
index 8b74514..889a936 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/PinEntryException.java
+++ b/dex/src/main/java/com/android/dex/util/ByteArrayByteInput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 The Android Open Source Project
+ * 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.
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
-// public for testing by CertPinManagerTest
-public class PinEntryException extends Exception {
+public final class ByteArrayByteInput implements ByteInput {
- PinEntryException() {
+ private final byte[] bytes;
+ private int position;
+
+ public ByteArrayByteInput(byte... bytes) {
+ this.bytes = bytes;
}
- PinEntryException(String msg) {
- super(msg);
+ @Override public byte readByte() {
+ return bytes[position++];
}
}
-
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/dex/src/main/java/com/android/dex/util/ByteInput.java
similarity index 66%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
copy to dex/src/main/java/com/android/dex/util/ByteInput.java
index 548e9c5..f1a7196 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/dex/src/main/java/com/android/dex/util/ByteInput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,8 +14,17 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
-public interface OpenSSLKeyHolder {
- public OpenSSLKey getOpenSSLKey();
+/**
+ * A byte source.
+ */
+public interface ByteInput {
+
+ /**
+ * Returns a byte.
+ *
+ * @throws IndexOutOfBoundsException if all bytes have been read.
+ */
+ byte readByte();
}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java b/dex/src/main/java/com/android/dex/util/ByteOutput.java
similarity index 66%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
copy to dex/src/main/java/com/android/dex/util/ByteOutput.java
index 548e9c5..eb77040 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLKeyHolder.java
+++ b/dex/src/main/java/com/android/dex/util/ByteOutput.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,8 +14,17 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package com.android.dex.util;
-public interface OpenSSLKeyHolder {
- public OpenSSLKey getOpenSSLKey();
+/**
+ * A byte sink.
+ */
+public interface ByteOutput {
+
+ /**
+ * Writes a byte.
+ *
+ * @throws IndexOutOfBoundsException if all bytes have been written.
+ */
+ void writeByte(int i);
}
diff --git a/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java b/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java
new file mode 100644
index 0000000..5dfd954
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/ExceptionWithContext.java
@@ -0,0 +1,148 @@
+/*
+ * 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 com.android.dex.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Exception which carries around structured context.
+ */
+public class ExceptionWithContext extends RuntimeException {
+ /** {@code non-null;} human-oriented context of the exception */
+ private StringBuffer context;
+
+ /**
+ * Augments the given exception with the given context, and return the
+ * result. The result is either the given exception if it was an
+ * {@link ExceptionWithContext}, or a newly-constructed exception if it
+ * was not.
+ *
+ * @param ex {@code non-null;} the exception to augment
+ * @param str {@code non-null;} context to add
+ * @return {@code non-null;} an appropriate instance
+ */
+ public static ExceptionWithContext withContext(Throwable ex, String str) {
+ ExceptionWithContext ewc;
+
+ if (ex instanceof ExceptionWithContext) {
+ ewc = (ExceptionWithContext) ex;
+ } else {
+ ewc = new ExceptionWithContext(ex);
+ }
+
+ ewc.addContext(str);
+ return ewc;
+ }
+
+ /**
+ * Constructs an instance.
+ *
+ * @param message human-oriented message
+ */
+ public ExceptionWithContext(String message) {
+ this(message, null);
+ }
+
+ /**
+ * Constructs an instance.
+ *
+ * @param cause {@code null-ok;} exception that caused this one
+ */
+ public ExceptionWithContext(Throwable cause) {
+ this(null, cause);
+ }
+
+ /**
+ * Constructs an instance.
+ *
+ * @param message human-oriented message
+ * @param cause {@code null-ok;} exception that caused this one
+ */
+ public ExceptionWithContext(String message, Throwable cause) {
+ super((message != null) ? message :
+ (cause != null) ? cause.getMessage() : null,
+ cause);
+
+ if (cause instanceof ExceptionWithContext) {
+ String ctx = ((ExceptionWithContext) cause).context.toString();
+ context = new StringBuffer(ctx.length() + 200);
+ context.append(ctx);
+ } else {
+ context = new StringBuffer(200);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void printStackTrace(PrintStream out) {
+ super.printStackTrace(out);
+ out.println(context);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void printStackTrace(PrintWriter out) {
+ super.printStackTrace(out);
+ out.println(context);
+ }
+
+ /**
+ * Adds a line of context to this instance.
+ *
+ * @param str {@code non-null;} new context
+ */
+ public void addContext(String str) {
+ if (str == null) {
+ throw new NullPointerException("str == null");
+ }
+
+ context.append(str);
+ if (!str.endsWith("\n")) {
+ context.append('\n');
+ }
+ }
+
+ /**
+ * Gets the context.
+ *
+ * @return {@code non-null;} the context
+ */
+ public String getContext() {
+ return context.toString();
+ }
+
+ /**
+ * Prints the message and context.
+ *
+ * @param out {@code non-null;} where to print to
+ */
+ public void printContext(PrintStream out) {
+ out.println(getMessage());
+ out.print(context);
+ }
+
+ /**
+ * Prints the message and context.
+ *
+ * @param out {@code non-null;} where to print to
+ */
+ public void printContext(PrintWriter out) {
+ out.println(getMessage());
+ out.print(context);
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/util/FileUtils.java b/dex/src/main/java/com/android/dex/util/FileUtils.java
new file mode 100644
index 0000000..4cea95c
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/FileUtils.java
@@ -0,0 +1,97 @@
+/*
+ * 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 com.android.dex.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+
+/**
+ * File I/O utilities.
+ */
+public final class FileUtils {
+ private FileUtils() {
+ }
+
+ /**
+ * Reads the named file, translating {@link IOException} to a
+ * {@link RuntimeException} of some sort.
+ *
+ * @param fileName {@code non-null;} name of the file to read
+ * @return {@code non-null;} contents of the file
+ */
+ public static byte[] readFile(String fileName) {
+ File file = new File(fileName);
+ return readFile(file);
+ }
+
+ /**
+ * Reads the given file, translating {@link IOException} to a
+ * {@link RuntimeException} of some sort.
+ *
+ * @param file {@code non-null;} the file to read
+ * @return {@code non-null;} contents of the file
+ */
+ public static byte[] readFile(File file) {
+ if (!file.exists()) {
+ throw new RuntimeException(file + ": file not found");
+ }
+
+ if (!file.isFile()) {
+ throw new RuntimeException(file + ": not a file");
+ }
+
+ if (!file.canRead()) {
+ throw new RuntimeException(file + ": file not readable");
+ }
+
+ long longLength = file.length();
+ int length = (int) longLength;
+ if (length != longLength) {
+ throw new RuntimeException(file + ": file too long");
+ }
+
+ byte[] result = new byte[length];
+
+ try {
+ FileInputStream in = new FileInputStream(file);
+ int at = 0;
+ while (length > 0) {
+ int amt = in.read(result, at, length);
+ if (amt == -1) {
+ throw new RuntimeException(file + ": unexpected EOF");
+ }
+ at += amt;
+ length -= amt;
+ }
+ in.close();
+ } catch (IOException ex) {
+ throw new RuntimeException(file + ": trouble reading", ex);
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns true if {@code fileName} names a .zip, .jar, or .apk.
+ */
+ public static boolean hasArchiveSuffix(String fileName) {
+ return fileName.endsWith(".zip")
+ || fileName.endsWith(".jar")
+ || fileName.endsWith(".apk");
+ }
+}
diff --git a/dex/src/main/java/com/android/dex/util/Unsigned.java b/dex/src/main/java/com/android/dex/util/Unsigned.java
new file mode 100644
index 0000000..cb50d0a
--- /dev/null
+++ b/dex/src/main/java/com/android/dex/util/Unsigned.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.dex.util;
+
+/**
+ * Unsigned arithmetic over Java's signed types.
+ */
+public final class Unsigned {
+ private Unsigned() {}
+
+ public static int compare(short ushortA, short ushortB) {
+ if (ushortA == ushortB) {
+ return 0;
+ }
+ int a = ushortA & 0xFFFF;
+ int b = ushortB & 0xFFFF;
+ return a < b ? -1 : 1;
+ }
+
+ public static int compare(int uintA, int uintB) {
+ if (uintA == uintB) {
+ return 0;
+ }
+ long a = uintA & 0xFFFFFFFFL;
+ long b = uintB & 0xFFFFFFFFL;
+ return a < b ? -1 : 1;
+ }
+}
diff --git a/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java b/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java
new file mode 100644
index 0000000..a4ca376
--- /dev/null
+++ b/dex/src/test/java/com/android/dex/EncodedValueReaderTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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 com.android.dex;
+
+import com.android.dex.util.ByteArrayByteInput;
+import junit.framework.TestCase;
+
+public final class EncodedValueReaderTest extends TestCase {
+
+ public void testReadByte() {
+ assertEquals((byte) 0x80, readerOf(0, 0x80).readByte());
+ assertEquals((byte) 0xff, readerOf(0, 0xff).readByte());
+ assertEquals((byte) 0x00, readerOf(0, 0x00).readByte());
+ assertEquals((byte) 0x01, readerOf(0, 0x01).readByte());
+ assertEquals((byte) 0x7f, readerOf(0, 0x7f).readByte());
+ }
+
+ public void testReadShort() {
+ assertEquals((short) 0x8000, readerOf(34, 0x00, 0x80).readShort());
+ assertEquals((short) 0, readerOf( 2, 0x00).readShort());
+ assertEquals((short) 0xab, readerOf(34, 0xab, 0x00).readShort());
+ assertEquals((short) 0xabcd, readerOf(34, 0xcd, 0xab).readShort());
+ assertEquals((short) 0x7FFF, readerOf(34, 0xff, 0x7f).readShort());
+ }
+
+ public void testReadInt() {
+ assertEquals(0x80000000, readerOf(100, 0x00, 0x00, 0x00, 0x80).readInt());
+ assertEquals( 0x00, readerOf( 4, 0x00).readInt());
+ assertEquals( 0xab, readerOf( 36, 0xab, 0x00).readInt());
+ assertEquals( 0xabcd, readerOf( 68, 0xcd, 0xab, 0x00).readInt());
+ assertEquals( 0xabcdef, readerOf(100, 0xef, 0xcd, 0xab, 0x00).readInt());
+ assertEquals(0xabcdef01, readerOf(100, 0x01, 0xef, 0xcd, 0xab).readInt());
+ assertEquals(0x7fffffff, readerOf(100, 0xff, 0xff, 0xff, 127).readInt());
+ }
+
+ public void testReadLong() {
+ assertEquals(0x8000000000000000L, readerOf( -26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80).readLong());
+ assertEquals( 0x00L, readerOf( 6, 0x00).readLong());
+ assertEquals( 0xabL, readerOf( 38, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdL, readerOf( 70, 0xcd, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdefL, readerOf( 102, 0xef, 0xcd, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdef01L, readerOf(-122, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdef0123L, readerOf( -90, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdef012345L, readerOf( -58, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+ assertEquals( 0xabcdef01234567L, readerOf( -26, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x00).readLong());
+ assertEquals(0xabcdef0123456789L, readerOf( -26, 0x89, 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab).readLong());
+ assertEquals(0x7fffffffffffffffL, readerOf( -26, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f).readLong());
+ }
+
+ public void testReadFloat() {
+ assertEquals(Float.NEGATIVE_INFINITY, readerOf(48, -128, -1).readFloat());
+ assertEquals(Float.POSITIVE_INFINITY, readerOf(48, -128, 127).readFloat());
+ assertEquals(Float.NaN, readerOf(48, -64, 127).readFloat());
+ assertEquals(-0.0f, readerOf(16, -128).readFloat());
+ assertEquals(0.0f, readerOf(16, 0).readFloat());
+ assertEquals(0.5f, readerOf(16, 63).readFloat());
+ assertEquals(1f, readerOf(48, -128, 63).readFloat());
+ assertEquals(1.0E06f, readerOf(80, 36, 116, 73).readFloat());
+ assertEquals(1.0E12f, readerOf(112, -91, -44, 104, 83).readFloat());
+ }
+
+ public void testReadDouble() {
+ assertEquals(Double.NEGATIVE_INFINITY, readerOf(49, -16, -1).readDouble());
+ assertEquals(Double.POSITIVE_INFINITY, readerOf(49, -16, 127).readDouble());
+ assertEquals(Double.NaN, readerOf(49, -8, 127).readDouble());
+ assertEquals(-0.0, readerOf(17, -128).readDouble());
+ assertEquals(0.0, readerOf(17, 0).readDouble());
+ assertEquals(0.5, readerOf(49, -32, 63).readDouble());
+ assertEquals(1.0, readerOf(49, -16, 63).readDouble());
+ assertEquals(1.0E06, readerOf(113, -128, -124, 46, 65).readDouble());
+ assertEquals(1.0E12, readerOf(-111, -94, -108, 26, 109, 66).readDouble());
+ assertEquals(1.0E24, readerOf(-15, -76, -99, -39, 121, 67, 120, -22, 68).readDouble());
+ }
+
+ public void testReadChar() {
+ assertEquals('\u0000', readerOf( 3, 0x00).readChar());
+ assertEquals('\u00ab', readerOf( 3, 0xab).readChar());
+ assertEquals('\uabcd', readerOf(35, 0xcd, 0xab).readChar());
+ assertEquals('\uffff', readerOf(35, 0xff, 0xff).readChar());
+ }
+
+ public void testReadBoolean() {
+ assertEquals(true, readerOf(63).readBoolean());
+ assertEquals(false, readerOf(31).readBoolean());
+ }
+
+ public void testReadNull() {
+ readerOf(30).readNull();
+ }
+
+ public void testReadReference() {
+ assertEquals( 0xab, readerOf(0x17, 0xab).readString());
+ assertEquals( 0xabcd, readerOf(0x37, 0xcd, 0xab).readString());
+ assertEquals( 0xabcdef, readerOf(0x57, 0xef, 0xcd, 0xab).readString());
+ assertEquals(0xabcdef01, readerOf(0x77, 0x01, 0xef, 0xcd, 0xab).readString());
+ }
+
+ public void testReadWrongType() {
+ try {
+ readerOf(0x17, 0xab).readField();
+ fail();
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ private EncodedValueReader readerOf(int... bytes) {
+ byte[] data = new byte[bytes.length];
+ for (int i = 0; i < bytes.length; i++) {
+ data[i] = (byte) bytes[i];
+ }
+ return new EncodedValueReader(new ByteArrayByteInput(data));
+ }
+}
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
index dfc65e7..ae70c55 100644
--- a/expectations/brokentests.txt
+++ b/expectations/brokentests.txt
@@ -543,17 +543,6 @@
substring: "GMT-07:00"
},
{
- description: "These harmony tests are broken. The RI doesn't ship with es__TRADITIONAL, so
- they have incorrect expectations.
- http://b/2608750",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.text.tests.java.text.RuleBasedCollatorTest#testGetCollationElementIteratorCharacterIterator",
- "org.apache.harmony.text.tests.java.text.RuleBasedCollatorTest#testGetCollationElementIteratorString"
- ],
- substring: "expected:<1> but was:<2>"
-},
-{
description: "This test fails because on Android, RuleBasedCollators default to
CANONICAL_DECOMPOSITION, not NO_DECOMPOSITION.",
result: EXEC_FAILED,
@@ -768,12 +757,6 @@
substring: "junit.framework.AssertionFailedError: expected:<3> but was:<2>"
},
{
- description: "this is testing exception priorities",
- result: EXEC_FAILED,
- name: "org.apache.harmony.nio.tests.java.nio.channels.DatagramChannelTest#testReadByteBuffer_readOnlyBuf",
- substring: "java.lang.IllegalArgumentException: read-only buffer"
-},
-{
description: "ICU doesn't provide localized pattern characters, and these tests assume the locale they're using has them.",
result: EXEC_FAILED,
name: "org.apache.harmony.text.tests.java.text.SimpleDateFormatTest#test_applyLocalizedPatternLjava_lang_String",
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 5d7f716..33f381f 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -3,6 +3,16 @@
*/
[
{
+ 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
+},
+{
+ description: "our regex implementation calls toString on CharSequences",
+ name: "org.apache.harmony.luni.tests.java.util.ScannerParseLargeFileBenchmarkTest#testParseLargeFile",
+ bug: 10133206
+},
+{
description: "Package.getPackages(), ClassLoader.getPackages() both omit results",
name: "libcore.java.lang.PackageTest#testGetPackages",
bug: 5171136
@@ -249,11 +259,6 @@
bug: 2702411
},
{
- description: "Pre-NIO aliases not implemented",
- name: "libcore.java.nio.charset.CharsetTest#test_preNioAliases",
- bug: 3032697
-},
-{
description: "HTTPS proxy broken on host",
names: [
"org.apache.harmony.luni.tests.internal.net.www.protocol.https.HttpsURLConnectionTest#testConsequentProxyConnection",
@@ -952,7 +957,7 @@
name: "tests.api.javax.net.ssl.SSLEngineTest#testHandshake"
},
{
- description: "org.apache.harmony.xnet.provider.jsse.SSLEngineImpl#getDelegatedTask() throws NPE instead of
+ description: "com.android.org.conscrypt.SSLEngineImpl#getDelegatedTask() throws NPE instead of
returning null",
bug: 3403706,
name: "tests.api.javax.net.ssl.SSLEngineTest#test_getDelegatedTask"
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
similarity index 79%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
index 330937f..b80f3a9 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationFormatErrorTest.java
@@ -21,18 +21,32 @@
import junit.framework.TestCase;
+/**
+ * Test case of java.lang.annotation.AnnotationFormatError
+ */
public class AnnotationFormatErrorTest extends TestCase {
+ /**
+ * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(String)
+ */
+ @SuppressWarnings("nls")
public void test_constructorLjava_lang_String() {
AnnotationFormatError e = new AnnotationFormatError("some message");
assertEquals("some message", e.getMessage());
}
+ /**
+ * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(Throwable)
+ */
public void test_constructorLjava_lang_Throwable() {
IllegalArgumentException iae = new IllegalArgumentException();
AnnotationFormatError e = new AnnotationFormatError(iae);
assertSame(iae, e.getCause());
}
+ /**
+ * @tests java.lang.annotation.AnnotationFormatError#AnnotationFormatError(String,Throwable)
+ */
+ @SuppressWarnings("nls")
public void test_constructorLjava_lang_StringLjava_lang_Throwable() {
IllegalArgumentException iae = new IllegalArgumentException();
AnnotationFormatError e = new AnnotationFormatError("some message", iae);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
new file mode 100644
index 0000000..37ee8c1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/AnnotationTypeMismatchExceptionTest.java
@@ -0,0 +1,46 @@
+/*
+ * 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.annotation.tests.java.lang.annotation;
+
+import java.lang.annotation.AnnotationTypeMismatchException;
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+/**
+ * Test case of java.lang.annotation.AnnotationTypeMismatchException
+ */
+public class AnnotationTypeMismatchExceptionTest extends TestCase {
+
+ /**
+ * @throws ClassNotFoundException
+ * @throws SecurityException
+ * @tests java.lang.annotation.AnnotationTypeMismatchException#AnnotationTypeMismatchException(Method,
+ * String)
+ */
+ @SuppressWarnings("nls")
+ public void test_constructorLjava_lang_reflect_MethodLjava_lang_String() throws SecurityException, ClassNotFoundException {
+ Method[] methods = Class.forName("java.lang.String").getMethods();
+ Method m = methods[0];
+ AnnotationTypeMismatchException e = new AnnotationTypeMismatchException(
+ m, "some type");
+ assertNotNull("can not instantiate AnnotationTypeMismatchException", e);
+ assertSame("wrong method name", m, e.element());
+ assertEquals("wrong found type", "some type", e.foundType());
+ }
+}
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
similarity index 79%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
index 6c99f74..d81cabd 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/ElementTypeTest.java
@@ -22,13 +22,23 @@
import junit.framework.TestCase;
+/**
+ * Test case of java.lang.annotation.ElementType
+ */
public class ElementTypeTest extends TestCase {
+ /**
+ * @throws Exception
+ * @tests java.lang.annotation.ElementType#valueOf(String)
+ */
+ @SuppressWarnings("nls")
public void test_valueOfLjava_lang_String() throws Exception {
- assertSame(ElementType.ANNOTATION_TYPE, ElementType.valueOf("ANNOTATION_TYPE"));
+ assertSame(ElementType.ANNOTATION_TYPE, ElementType
+ .valueOf("ANNOTATION_TYPE"));
assertSame(ElementType.CONSTRUCTOR, ElementType.valueOf("CONSTRUCTOR"));
assertSame(ElementType.FIELD, ElementType.valueOf("FIELD"));
- assertSame(ElementType.LOCAL_VARIABLE, ElementType.valueOf("LOCAL_VARIABLE"));
+ assertSame(ElementType.LOCAL_VARIABLE, ElementType
+ .valueOf("LOCAL_VARIABLE"));
assertSame(ElementType.METHOD, ElementType.valueOf("METHOD"));
assertSame(ElementType.PACKAGE, ElementType.valueOf("PACKAGE"));
assertSame(ElementType.PARAMETER, ElementType.valueOf("PARAMETER"));
@@ -41,6 +51,11 @@
}
}
+ /**
+ * @throws Exception
+ * @tests java.lang.annotation.ElementType#values()
+ */
+ @SuppressWarnings("nls")
public void test_values() throws Exception {
ElementType[] values = ElementType.values();
assertTrue(values.length > 1);
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
similarity index 82%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
index 8e1ca80..d44b90a 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/IncompleteAnnotationExceptionTest.java
@@ -21,8 +21,13 @@
import junit.framework.TestCase;
+/**
+ *
+ */
public class IncompleteAnnotationExceptionTest extends TestCase {
+
/*
+ * Class under test for void IncompleteAnnotationException(String)
* Regression for HARMONY-2477
*/
public void testNullType() {
@@ -34,10 +39,18 @@
}
}
- public void test_constructorLjava_lang_Class_Ljava_lang_String() throws Exception {
+ /**
+ * @throws Exception
+ * @tests java.lang.annotation.IncompleteAnnotationException#IncompleteAnnotationException(Class,
+ * String)
+ */
+ @SuppressWarnings("nls")
+ public void test_constructorLjava_lang_Class_Ljava_lang_String()
+ throws Exception {
Class clazz = String.class;
String elementName = "some element";
- IncompleteAnnotationException e = new IncompleteAnnotationException(clazz, elementName);
+ IncompleteAnnotationException e = new IncompleteAnnotationException(
+ clazz, elementName);
assertNotNull("can not instantiate IncompleteAnnotationException", e);
assertSame("wrong annotation type", clazz, e.annotationType());
assertSame("wrong element name", elementName, e.elementName());
diff --git a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
similarity index 71%
rename from luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
index b1c2565..c4f7c03 100644
--- a/luni/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/annotation/tests/java/lang/annotation/RetentionPolicyTest.java
@@ -22,11 +22,22 @@
import junit.framework.TestCase;
+/**
+ * Test case of java.lang.annotation.RetentionPolicy
+ */
public class RetentionPolicyTest extends TestCase {
+ /**
+ * @throws Exception
+ * @tests java.lang.annotation.RetentionPolicy#valueOf(String)
+ */
+ @SuppressWarnings("nls")
public void test_valueOfLjava_lang_String() throws Exception {
- assertSame(RetentionPolicy.CLASS, RetentionPolicy.valueOf("CLASS"));
- assertSame(RetentionPolicy.RUNTIME, RetentionPolicy.valueOf("RUNTIME"));
- assertSame(RetentionPolicy.SOURCE, RetentionPolicy.valueOf("SOURCE"));
+ assertSame(RetentionPolicy.CLASS, RetentionPolicy
+ .valueOf("CLASS"));
+ assertSame(RetentionPolicy.RUNTIME, RetentionPolicy
+ .valueOf("RUNTIME"));
+ assertSame(RetentionPolicy.SOURCE, RetentionPolicy
+ .valueOf("SOURCE"));
try {
RetentionPolicy.valueOf("OTHER");
fail("Should throw an IllegalArgumentException");
@@ -35,6 +46,11 @@
}
}
+ /**
+ * @throws Exception
+ * @tests java.lang.annotation.RetentionPolicy#values()
+ */
+ @SuppressWarnings("nls")
public void test_values() throws Exception {
RetentionPolicy[] values = RetentionPolicy.values();
assertTrue(values.length > 1);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java
new file mode 100644
index 0000000..f101c73
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/io/BufferedReaderTest.java
@@ -0,0 +1,592 @@
+/*
+ * 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.luni.tests.java.io;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PipedReader;
+import java.io.Reader;
+import java.io.StringReader;
+
+import junit.framework.TestCase;
+import tests.support.Support_StringReader;
+
+public class BufferedReaderTest extends TestCase {
+
+ BufferedReader br;
+
+ String testString = "Test_All_Tests\nTest_java_io_BufferedInputStream\nTest_java_io_BufferedOutputStream\nTest_java_io_ByteArrayInputStream\nTest_java_io_ByteArrayOutputStream\nTest_java_io_DataInputStream\nTest_java_io_File\nTest_java_io_FileDescriptor\nTest_java_io_FileInputStream\nTest_java_io_FileNotFoundException\nTest_java_io_FileOutputStream\nTest_java_io_FilterInputStream\nTest_java_io_FilterOutputStream\nTest_java_io_InputStream\nTest_java_io_IOException\nTest_java_io_OutputStream\nTest_java_io_PrintStream\nTest_java_io_RandomAccessFile\nTest_java_io_SyncFailedException\nTest_java_lang_AbstractMethodError\nTest_java_lang_ArithmeticException\nTest_java_lang_ArrayIndexOutOfBoundsException\nTest_java_lang_ArrayStoreException\nTest_java_lang_Boolean\nTest_java_lang_Byte\nTest_java_lang_Character\nTest_java_lang_Class\nTest_java_lang_ClassCastException\nTest_java_lang_ClassCircularityError\nTest_java_lang_ClassFormatError\nTest_java_lang_ClassLoader\nTest_java_lang_ClassNotFoundException\nTest_java_lang_CloneNotSupportedException\nTest_java_lang_Double\nTest_java_lang_Error\nTest_java_lang_Exception\nTest_java_lang_ExceptionInInitializerError\nTest_java_lang_Float\nTest_java_lang_IllegalAccessError\nTest_java_lang_IllegalAccessException\nTest_java_lang_IllegalArgumentException\nTest_java_lang_IllegalMonitorStateException\nTest_java_lang_IllegalThreadStateException\nTest_java_lang_IncompatibleClassChangeError\nTest_java_lang_IndexOutOfBoundsException\nTest_java_lang_InstantiationError\nTest_java_lang_InstantiationException\nTest_java_lang_Integer\nTest_java_lang_InternalError\nTest_java_lang_InterruptedException\nTest_java_lang_LinkageError\nTest_java_lang_Long\nTest_java_lang_Math\nTest_java_lang_NegativeArraySizeException\nTest_java_lang_NoClassDefFoundError\nTest_java_lang_NoSuchFieldError\nTest_java_lang_NoSuchMethodError\nTest_java_lang_NullPointerException\nTest_java_lang_Number\nTest_java_lang_NumberFormatException\nTest_java_lang_Object\nTest_java_lang_OutOfMemoryError\nTest_java_lang_RuntimeException\nTest_java_lang_SecurityManager\nTest_java_lang_Short\nTest_java_lang_StackOverflowError\nTest_java_lang_String\nTest_java_lang_StringBuffer\nTest_java_lang_StringIndexOutOfBoundsException\nTest_java_lang_System\nTest_java_lang_Thread\nTest_java_lang_ThreadDeath\nTest_java_lang_ThreadGroup\nTest_java_lang_Throwable\nTest_java_lang_UnknownError\nTest_java_lang_UnsatisfiedLinkError\nTest_java_lang_VerifyError\nTest_java_lang_VirtualMachineError\nTest_java_lang_vm_Image\nTest_java_lang_vm_MemorySegment\nTest_java_lang_vm_ROMStoreException\nTest_java_lang_vm_VM\nTest_java_lang_Void\nTest_java_net_BindException\nTest_java_net_ConnectException\nTest_java_net_DatagramPacket\nTest_java_net_DatagramSocket\nTest_java_net_DatagramSocketImpl\nTest_java_net_InetAddress\nTest_java_net_NoRouteToHostException\nTest_java_net_PlainDatagramSocketImpl\nTest_java_net_PlainSocketImpl\nTest_java_net_Socket\nTest_java_net_SocketException\nTest_java_net_SocketImpl\nTest_java_net_SocketInputStream\nTest_java_net_SocketOutputStream\nTest_java_net_UnknownHostException\nTest_java_util_ArrayEnumerator\nTest_java_util_Date\nTest_java_util_EventObject\nTest_java_util_HashEnumerator\nTest_java_util_Hashtable\nTest_java_util_Properties\nTest_java_util_ResourceBundle\nTest_java_util_tm\nTest_java_util_Vector\n";
+
+ /**
+ * The spec says that BufferedReader.readLine() considers only "\r", "\n"
+ * and "\r\n" to be line separators. We must not permit additional separator
+ * characters.
+ */
+ public void test_readLine_IgnoresEbcdic85Characters() throws IOException {
+ assertLines("A\u0085B", "A\u0085B");
+ }
+
+ public void test_readLine_Separators() throws IOException {
+ assertLines("A\nB\nC", "A", "B", "C");
+ assertLines("A\rB\rC", "A", "B", "C");
+ assertLines("A\r\nB\r\nC", "A", "B", "C");
+ assertLines("A\n\rB\n\rC", "A", "", "B", "", "C");
+ assertLines("A\n\nB\n\nC", "A", "", "B", "", "C");
+ assertLines("A\r\rB\r\rC", "A", "", "B", "", "C");
+ assertLines("A\n\n", "A", "");
+ assertLines("A\n\r", "A", "");
+ assertLines("A\r\r", "A", "");
+ assertLines("A\r\n", "A");
+ assertLines("A\r\n\r\n", "A", "");
+ }
+
+ private void assertLines(String in, String... lines) throws IOException {
+ BufferedReader bufferedReader
+ = new BufferedReader(new Support_StringReader(in));
+ for (String line : lines) {
+ assertEquals(line, bufferedReader.readLine());
+ }
+ assertNull(bufferedReader.readLine());
+ }
+
+ /**
+ * @tests java.io.BufferedReader#BufferedReader(java.io.Reader)
+ */
+ public void test_ConstructorLjava_io_Reader() {
+ // Test for method java.io.BufferedReader(java.io.Reader)
+ assertTrue("Used in tests", true);
+ }
+
+ /**
+ * @tests java.io.BufferedReader#BufferedReader(java.io.Reader, int)
+ */
+ public void test_ConstructorLjava_io_ReaderI() {
+ // Test for method java.io.BufferedReader(java.io.Reader, int)
+ assertTrue("Used in tests", true);
+ }
+
+ /**
+ * @tests java.io.BufferedReader#close()
+ */
+ public void test_close() {
+ // Test for method void java.io.BufferedReader.close()
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.close();
+ br.read();
+ fail("Read on closed stream");
+ } catch (IOException x) {
+ return;
+ }
+ }
+
+ /**
+ * @tests java.io.BufferedReader#mark(int)
+ */
+ public void test_markI() throws IOException {
+ // Test for method void java.io.BufferedReader.mark(int)
+ char[] buf = null;
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.skip(500);
+ br.mark(1000);
+ br.skip(250);
+ br.reset();
+ buf = new char[testString.length()];
+ br.read(buf, 0, 500);
+ assertTrue("Failed to set mark properly", testString.substring(500,
+ 1000).equals(new String(buf, 0, 500)));
+
+ try {
+ br = new BufferedReader(new Support_StringReader(testString), 800);
+ br.skip(500);
+ br.mark(250);
+ br.read(buf, 0, 1000);
+ br.reset();
+ fail("Failed to invalidate mark properly");
+ } catch (IOException x) {
+ // Expected
+ }
+
+ char[] chars = new char[256];
+ for (int i = 0; i < 256; i++)
+ chars[i] = (char) i;
+ Reader in = new BufferedReader(new Support_StringReader(new String(
+ chars)), 12);
+
+ in.skip(6);
+ in.mark(14);
+ in.read(new char[14], 0, 14);
+ in.reset();
+ assertTrue("Wrong chars", in.read() == (char) 6
+ && in.read() == (char) 7);
+
+ in = new BufferedReader(new Support_StringReader(new String(chars)), 12);
+ in.skip(6);
+ in.mark(8);
+ in.skip(7);
+ in.reset();
+ assertTrue("Wrong chars 2", in.read() == (char) 6
+ && in.read() == (char) 7);
+
+ BufferedReader br = new BufferedReader(new StringReader("01234"), 2);
+ br.mark(3);
+ char[] carray = new char[3];
+ int result = br.read(carray);
+ assertEquals(3, result);
+ assertEquals("Assert 0:", '0', carray[0]);
+ assertEquals("Assert 1:", '1', carray[1]);
+ assertEquals("Assert 2:", '2', carray[2]);
+ assertEquals("Assert 3:", '3', br.read());
+
+ br = new BufferedReader(new StringReader("01234"), 2);
+ br.mark(3);
+ carray = new char[4];
+ result = br.read(carray);
+ assertEquals("Assert 4:", 4, result);
+ assertEquals("Assert 5:", '0', carray[0]);
+ assertEquals("Assert 6:", '1', carray[1]);
+ assertEquals("Assert 7:", '2', carray[2]);
+ assertEquals("Assert 8:", '3', carray[3]);
+ assertEquals("Assert 9:", '4', br.read());
+ assertEquals("Assert 10:", -1, br.read());
+
+ BufferedReader reader = new BufferedReader(new StringReader("01234"));
+ reader.mark(Integer.MAX_VALUE);
+ reader.read();
+ reader.close();
+ }
+
+ /**
+ * @tests java.io.BufferedReader#markSupported()
+ */
+ public void test_markSupported() {
+ // Test for method boolean java.io.BufferedReader.markSupported()
+ br = new BufferedReader(new Support_StringReader(testString));
+ assertTrue("markSupported returned false", br.markSupported());
+ }
+
+ /**
+ * @tests java.io.BufferedReader#read()
+ */
+ public void test_read() throws IOException {
+ // Test for method int java.io.BufferedReader.read()
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ int r = br.read();
+ assertTrue("Char read improperly", testString.charAt(0) == r);
+ br = new BufferedReader(new Support_StringReader(new String(
+ new char[] { '\u8765' })));
+ assertTrue("Wrong double byte character", br.read() == '\u8765');
+ } catch (java.io.IOException e) {
+ fail("Exception during read test");
+ }
+
+ char[] chars = new char[256];
+ for (int i = 0; i < 256; i++)
+ chars[i] = (char) i;
+ Reader in = new BufferedReader(new Support_StringReader(new String(
+ chars)), 12);
+ try {
+ assertEquals("Wrong initial char", 0, in.read()); // Fill the
+ // buffer
+ char[] buf = new char[14];
+ in.read(buf, 0, 14); // Read greater than the buffer
+ assertTrue("Wrong block read data", new String(buf)
+ .equals(new String(chars, 1, 14)));
+ assertEquals("Wrong chars", 15, in.read()); // Check next byte
+ } catch (IOException e) {
+ fail("Exception during read test 2:" + e);
+ }
+
+ // regression test for HARMONY-841
+ assertTrue(new BufferedReader(new CharArrayReader(new char[5], 1, 0), 2).read() == -1);
+ }
+
+ /**
+ * @tests java.io.BufferedReader#read(char[], int, int)
+ */
+ public void test_read$CII() throws Exception{
+ char[] ca = new char[2];
+ BufferedReader toRet = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(new byte[0])));
+
+ /* Null buffer should throw NPE even when len == 0 */
+ try {
+ toRet.read(null, 1, 0);
+ fail("null buffer reading zero bytes should throw NPE");
+ } catch (NullPointerException e) {
+ //expected
+ }
+
+ try {
+ toRet.close();
+ } catch (IOException e) {
+ fail("unexpected 1: " + e);
+ }
+
+ try {
+ toRet.read(null, 1, 0);
+ fail("null buffer reading zero bytes on closed stream should throw IOException");
+ } catch (IOException e) {
+ //expected
+ }
+
+ /* Closed reader should throw IOException reading zero bytes */
+ try {
+ toRet.read(ca, 0, 0);
+ fail("Reading zero bytes on a closed reader should not work");
+ } catch (IOException e) {
+ // expected
+ }
+
+ /*
+ * Closed reader should throw IOException in preference to index out of
+ * bounds
+ */
+ try {
+ // Read should throw IOException before
+ // ArrayIndexOutOfBoundException
+ toRet.read(ca, 1, 5);
+ fail("IOException should have been thrown");
+ } catch (IOException e) {
+ // expected
+ }
+
+ // Test to ensure that a drained stream returns 0 at EOF
+ toRet = new BufferedReader(new InputStreamReader(
+ new ByteArrayInputStream(new byte[2])));
+ try {
+ assertEquals("Emptying the reader should return two bytes", 2,
+ toRet.read(ca, 0, 2));
+ assertEquals("EOF on a reader should be -1", -1, toRet.read(ca, 0,
+ 2));
+ assertEquals("Reading zero bytes at EOF should work", 0, toRet
+ .read(ca, 0, 0));
+ } catch (IOException ex) {
+ fail("Unexpected IOException : " + ex.getLocalizedMessage());
+ }
+
+ // Test for method int java.io.BufferedReader.read(char [], int, int)
+ try {
+ char[] buf = new char[testString.length()];
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.read(buf, 50, 500);
+ assertTrue("Chars read improperly", new String(buf, 50, 500)
+ .equals(testString.substring(0, 500)));
+ } catch (java.io.IOException e) {
+ fail("Exception during read test");
+ }
+
+ BufferedReader bufin = new BufferedReader(new Reader() {
+ int size = 2, pos = 0;
+
+ char[] contents = new char[size];
+
+ public int read() throws IOException {
+ if (pos >= size)
+ throw new IOException("Read past end of data");
+ return contents[pos++];
+ }
+
+ public int read(char[] buf, int off, int len) throws IOException {
+ if (pos >= size)
+ throw new IOException("Read past end of data");
+ int toRead = len;
+ if (toRead > (size - pos))
+ toRead = size - pos;
+ System.arraycopy(contents, pos, buf, off, toRead);
+ pos += toRead;
+ return toRead;
+ }
+
+ public boolean ready() throws IOException {
+ return size - pos > 0;
+ }
+
+ public void close() throws IOException {
+ }
+ });
+ try {
+ bufin.read();
+ int result = bufin.read(new char[2], 0, 2);
+ assertTrue("Incorrect result: " + result, result == 1);
+ } catch (IOException e) {
+ fail("Unexpected: " + e);
+ }
+
+ //regression for HARMONY-831
+ try{
+ new BufferedReader(new PipedReader(), 9).read(new char[] {}, 7, 0);
+ fail("should throw IndexOutOfBoundsException");
+ }catch(IndexOutOfBoundsException e){
+ }
+
+ // Regression for HARMONY-54
+ char[] ch = {};
+ BufferedReader reader = new BufferedReader(new CharArrayReader(ch));
+ try {
+ // Check exception thrown when the reader is open.
+ reader.read(null, 1, 0);
+ fail("Assert 0: NullPointerException expected");
+ } catch (NullPointerException e) {
+ // Expected
+ }
+
+ // Now check IOException is thrown in preference to
+ // NullPointerexception when the reader is closed.
+ reader.close();
+ try {
+ reader.read(null, 1, 0);
+ fail("Assert 1: IOException expected");
+ } catch (IOException e) {
+ // Expected
+ }
+
+ try {
+ // And check that the IOException is thrown before
+ // ArrayIndexOutOfBoundException
+ reader.read(ch, 0, 42);
+ fail("Assert 2: IOException expected");
+ } catch (IOException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.io.BufferedReader#read(char[], int, int)
+ */
+ public void test_read_$CII_Exception() throws IOException {
+ br = new BufferedReader(new Support_StringReader(testString));
+ char[] nullCharArray = null;
+ char[] charArray = testString.toCharArray();
+
+ try {
+ br.read(nullCharArray, -1, -1);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ br.read(nullCharArray, -1, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ br.read(nullCharArray, 0, -1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ br.read(nullCharArray, 0, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ br.read(nullCharArray, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ br.read(charArray, -1, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ br.read(charArray, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ br.read(charArray, 0, 0);
+ br.read(charArray, 0, charArray.length);
+ br.read(charArray, charArray.length, 0);
+
+ try {
+ br.read(charArray, charArray.length + 1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+
+ try {
+ br.read(charArray, charArray.length + 1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+
+ br.close();
+
+ try {
+ br.read(nullCharArray, -1, -1);
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+
+ try {
+ br.read(charArray, -1, 0);
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+
+ try {
+ br.read(charArray, 0, -1);
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+ }
+ /**
+ * @tests java.io.BufferedReader#readLine()
+ */
+ public void test_readLine() {
+ // Test for method java.lang.String java.io.BufferedReader.readLine()
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ String r = br.readLine();
+ assertEquals("readLine returned incorrect string", "Test_All_Tests", r
+ );
+ } catch (java.io.IOException e) {
+ fail("Exception during readLine test");
+ }
+ }
+
+ /**
+ * @tests java.io.BufferedReader#ready()
+ */
+ public void test_ready() {
+ // Test for method boolean java.io.BufferedReader.ready()
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ assertTrue("ready returned false", br.ready());
+ } catch (java.io.IOException e) {
+ fail("Exception during ready test" + e.toString());
+ }
+ }
+
+ /**
+ * @tests java.io.BufferedReader#reset()
+ */
+ public void test_reset() {
+ // Test for method void java.io.BufferedReader.reset()
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.skip(500);
+ br.mark(900);
+ br.skip(500);
+ br.reset();
+ char[] buf = new char[testString.length()];
+ br.read(buf, 0, 500);
+ assertTrue("Failed to reset properly", testString.substring(500,
+ 1000).equals(new String(buf, 0, 500)));
+ } catch (java.io.IOException e) {
+ fail("Exception during reset test");
+ }
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.skip(500);
+ br.reset();
+ fail("Reset succeeded on unmarked stream");
+ } catch (IOException x) {
+ return;
+
+ }
+ }
+
+ public void test_reset_IOException() throws Exception {
+ int[] expected = new int[] { '1', '2', '3', '4', '5', '6', '7', '8',
+ '9', '0', -1 };
+ br = new BufferedReader(new Support_StringReader("1234567890"), 9);
+ br.mark(9);
+ for (int i = 0; i < 11; i++) {
+ assertEquals(expected[i], br.read());
+ }
+ try {
+ br.reset();
+ fail("should throw IOException");
+ } catch (IOException e) {
+ // Expected
+ }
+ for (int i = 0; i < 11; i++) {
+ assertEquals(-1, br.read());
+ }
+
+ br = new BufferedReader(new Support_StringReader("1234567890"));
+ br.mark(10);
+ for (int i = 0; i < 10; i++) {
+ assertEquals(expected[i], br.read());
+ }
+ br.reset();
+ for (int i = 0; i < 11; i++) {
+ assertEquals(expected[i], br.read());
+ }
+ }
+
+ /**
+ * @tests java.io.BufferedReader#skip(long)
+ */
+ public void test_skipJ() {
+ // Test for method long java.io.BufferedReader.skip(long)
+ try {
+ br = new BufferedReader(new Support_StringReader(testString));
+ br.skip(500);
+ char[] buf = new char[testString.length()];
+ br.read(buf, 0, 500);
+ assertTrue("Failed to set skip properly", testString.substring(500,
+ 1000).equals(new String(buf, 0, 500)));
+ } catch (java.io.IOException e) {
+ fail("Exception during skip test");
+ }
+
+ }
+
+ /**
+ * Sets up the fixture, for example, open a network connection. This method
+ * is called before a test is executed.
+ */
+ protected void setUp() {
+ }
+
+ /**
+ * Tears down the fixture, for example, close a network connection. This
+ * method is called after a test is executed.
+ */
+ protected void tearDown() {
+ try {
+ br.close();
+ } catch (Exception e) {
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java
new file mode 100644
index 0000000..117f211
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerParseLargeFileBenchmarkTest.java
@@ -0,0 +1,76 @@
+/* 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.luni.tests.java.util;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Scanner;
+
+import junit.framework.TestCase;
+
+public class ScannerParseLargeFileBenchmarkTest extends TestCase {
+
+ /**
+ * This test will check when parse a large file like more than 200M bytes if
+ * the Scanner will exhaust all heap memory
+ */
+ public void testParseLargeFile() throws Exception {
+ MyReader reader = new MyReader();
+ String delimiter = "\r?\n";
+ Scanner scanner = new Scanner(reader).useDelimiter(delimiter);
+
+ while (scanner.hasNext()) {
+ scanner.next();
+ }
+ scanner.close();
+ reader.close();
+ }
+
+ private static class MyReader extends Reader {
+ static final char[] CONTENT = "large file!\n".toCharArray();
+
+ static long fileLength = (8 << 21) * 12;
+
+ static boolean first = true;
+
+ static int position = 0;
+
+ private int count = 0;
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ @Override
+ public int read(char[] buf, int offset, int length) {
+ if (count >= fileLength) {
+ return -1;
+ }
+ if (first == true) {
+ position = 0;
+ first = false;
+ }
+ for (int i = offset; i < length; i++) {
+ buf[i] = CONTENT[(i + position) % CONTENT.length];
+ count++;
+ }
+
+ position = (length + position) % CONTENT.length;
+
+ return length - offset;
+ }
+ }
+}
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
new file mode 100644
index 0000000..459bce1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/ScannerTest.java
@@ -0,0 +1,5741 @@
+/* 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.luni.tests.java.util;
+
+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.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+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.ReadableByteChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.InputMismatchException;
+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 junit.framework.TestCase;
+
+public class ScannerTest extends TestCase {
+
+ private Scanner s;
+
+ private ServerSocket server;
+
+ private SocketAddress address;
+
+ private SocketChannel client;
+
+ private Socket serverSocket;
+
+ private OutputStream os;
+
+ private static class MockCloseable implements Closeable, Readable {
+
+ public void close() throws IOException {
+ throw new IOException();
+ }
+
+ public int read(CharBuffer cb) throws IOException {
+ throw new EOFException();
+ }
+
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(File)
+ */
+ public void test_ConstructorLjava_io_File() throws IOException {
+ File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ s = new Scanner(tmpFile);
+ assertNotNull(s);
+ s.close();
+ assertTrue(tmpFile.delete());
+
+ try {
+ s = new Scanner(tmpFile);
+ fail("should throw FileNotFoundException");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+ fos.write("test".getBytes());
+
+ s = new Scanner(tmpFile);
+ tmpFile.delete();
+
+ // Scanner(File = null)
+ try {
+ s = new Scanner((File) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // TODO: test if the default charset is used.
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(File, String)
+ */
+ public void test_ConstructorLjava_io_FileLjava_lang_String()
+ throws IOException {
+ File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ s = new Scanner(tmpFile, Charset.defaultCharset().name());
+ assertNotNull(s);
+ s.close();
+ assertTrue(tmpFile.delete());
+
+ try {
+ s = new Scanner(tmpFile, Charset.defaultCharset().name());
+ fail("should throw FileNotFoundException");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ try {
+ s = new Scanner(tmpFile, null);
+ fail("should throw FileNotFoundException");
+ } catch (FileNotFoundException e) {
+ // expected
+ }
+
+ tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ try {
+ s = new Scanner(tmpFile, "invalid charset");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ //fail on RI. File is opened but not closed when exception is thrown on
+ // RI.
+ assertTrue(tmpFile.delete());
+
+ // Scanner(File = null, Charset = null)
+ try {
+ s = new Scanner((File) null, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // Scanner(File = null, Charset = UTF-8)
+ try {
+ s = new Scanner((File) null, "UTF-8");
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // Scanner(File = null, Charset = invalid)
+ try {
+ s = new Scanner((File) null, "invalid");
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // 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
+ }
+
+ // TODO: test if the specified charset is used.
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(InputStream)
+ */
+ public void test_ConstructorLjava_io_InputStream() {
+ s = new Scanner(new PipedInputStream());
+ assertNotNull(s);
+ s.close();
+
+ // Scanner(InputStream)
+ try {
+ s = new Scanner((InputStream) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // TODO: test if the default charset is used.
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(InputStream, String)
+ */
+ public void test_ConstructorLjava_io_InputStreamLjava_lang_String() {
+ s = new Scanner(new PipedInputStream(), Charset.defaultCharset().name());
+ assertNotNull(s);
+ s.close();
+
+ try {
+ s = new Scanner((PipedInputStream) null, "invalid charset");
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ s = new Scanner(new PipedInputStream(), null);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ s = new Scanner(new PipedInputStream(), "invalid charset");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // TODO: test if the specified charset is used.
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(Readable)
+ */
+ public void test_ConstructorLjava_lang_Readable() {
+ s = new Scanner(new StringReader("test string"));
+ assertNotNull(s);
+ s.close();
+
+ // Scanner(Readable)
+ try {
+ s = new Scanner((Readable) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(ReadableByteChannel)
+ */
+ public void test_ConstructorLjava_nio_channels_ReadableByteChannel()
+ throws IOException {
+ File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ FileChannel fc = new FileOutputStream(tmpFile).getChannel();
+ s = new Scanner(fc);
+ assertNotNull(s);
+ s.close();
+ assertTrue(tmpFile.delete());
+
+ // Scanner(ReadableByteChannel)
+ try {
+ s = new Scanner((ReadableByteChannel) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // Test if the default charset is used.
+ String sampleData = "1 2 3 4 5 6 7 8 9 10";
+ File tempFile = File.createTempFile("harmony", "test");
+ tempFile.deleteOnExit();
+ FileOutputStream os = new FileOutputStream(tempFile);
+ os.write(sampleData.getBytes());
+ os.close();
+
+ FileInputStream is = new FileInputStream(tempFile);
+ FileChannel channel = is.getChannel();
+
+ Scanner s = new Scanner(channel);
+ int count = 0;
+ while (s.hasNextInt()) {
+ s.nextInt();
+ count++;
+ }
+ channel.close();
+ assertEquals(10, count);
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(ReadableByteChannel, String)
+ */
+ public void test_ConstructorLjava_nio_channels_ReadableByteChannelLjava_lang_String()
+ throws IOException {
+ File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ FileChannel fc = new FileOutputStream(tmpFile).getChannel();
+ s = new Scanner(fc, Charset.defaultCharset().name());
+ assertNotNull(s);
+ s.close();
+
+ fc = new FileOutputStream(tmpFile).getChannel();
+ try {
+ s = new Scanner(fc, "invalid charset");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ fc.close();
+ assertTrue(tmpFile.delete());
+
+ // Scanner(ReadableByteChannel = null, Charset = null)
+ try {
+ s = new Scanner((ReadableByteChannel) null, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // Scanner(ReadableByteChannel = null, Charset = invalid)
+ try {
+ s = new Scanner((ReadableByteChannel) null, "invalid");
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // Scanner(ReadableByteChannel, Charset = null)
+ try {
+ s = new Scanner(fc, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ // TODO: test if the specified charset is used.
+ }
+
+ /**
+ * @tests java.util.Scanner#Scanner(String)
+ */
+ public void test_ConstructorLjava_lang_String() {
+ s = new Scanner("test string");
+ assertNotNull(s);
+ s.close();
+
+ // Scanner(String)
+ try {
+ s = new Scanner((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.util.Scanner#close()
+ */
+ public void test_close() throws IOException {
+ File tmpFile = File.createTempFile("TestFileForScanner", ".tmp");
+ FileOutputStream fos = new FileOutputStream(tmpFile);
+ FileChannel fc = fos.getChannel();
+ s = new Scanner(fc);
+
+ // Write out a int before the scanner is closed, should be OK.
+ fos.write(12);
+
+ s.close();
+ assertFalse(fc.isOpen());
+
+ // Write out a int after the scanner is closed, IOException should be
+ // thrown out.
+ try {
+ fos.write(12);
+ fail("Should throw IOException");
+ } catch (IOException e) {
+ // expected
+ }
+
+ s.close(); // no exception should be thrown
+ assertTrue(tmpFile.delete());
+ }
+
+ /**
+ * @tests java.util.Scanner#ioException()
+ */
+ public void test_ioException() throws IOException {
+ MockCloseable mc = new MockCloseable();
+ s = new Scanner(mc);
+ assertNull(s.ioException()); // No operation, no exception
+
+ s.close(); // IOException should be cached
+ assertNotNull(s.ioException());
+ assertTrue(s.ioException() instanceof IOException);
+ }
+
+ /**
+ * @tests java.util.Scanner#delimiter()
+ */
+ public void test_delimiter() {
+ s = new Scanner("test");
+ Pattern pattern = s.delimiter();
+ assertEquals("\\p{javaWhitespace}+", pattern.toString());
+ }
+
+ /**
+ * @tests java.util.Scanner#useDelimiter(Pattern)
+ */
+ public void test_useDelimiter_LPattern() {
+ s = new Scanner("test");
+ s.useDelimiter(Pattern.compile("\\w+"));
+ assertEquals("\\w+", s.delimiter().toString());
+
+ s = new Scanner("test");
+ s.useDelimiter((Pattern) null);
+ assertNull(s.delimiter());
+ }
+
+ /**
+ * @tests java.util.Scanner#useDelimiter(String)
+ */
+ public void test_useDelimiter_String() {
+ s = new Scanner("test");
+ try {
+ s.useDelimiter((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ s = new Scanner("test");
+ s.useDelimiter("\\w+");
+ assertEquals("\\w+", s.delimiter().toString());
+ }
+
+ /**
+ * @tests java.util.Scanner#locale()
+ */
+ public void test_locale() {
+ s = new Scanner("test");
+ assertEquals(Locale.getDefault(), s.locale());
+ }
+
+ /**
+ * @tests java.util.Scanner#useLocale(Locale)
+ */
+ public void test_useLocale_LLocale() {
+ s = new Scanner("test");
+ try {
+ s.useLocale(null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ s.useLocale(new Locale("test", "test"));
+ assertEquals(new Locale("test", "test"), s.locale());
+ }
+
+ /**
+ * @tests java.util.Scanner#radix()
+ */
+ public void test_radix() {
+ s = new Scanner("test");
+ assertEquals(10, s.radix());
+ }
+
+ /**
+ * @tests java.util.Scanner#useRadix()
+ */
+ public void test_useRadix_I() {
+ s = new Scanner("test");
+ try {
+ s.useRadix(Character.MIN_RADIX - 1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ s.useRadix(Character.MAX_RADIX + 1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ s.useRadix(11);
+ assertEquals(11, s.radix());
+ }
+
+ /**
+ * @tests java.util.Scanner#remove()
+ */
+ public void test_remove() {
+ s = new Scanner("aab*b*").useDelimiter("\\*");
+ try {
+ s.remove();
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ //Expected
+ }
+ }
+
+ /**
+ * @tests java.util.Scanner#match()
+ */
+ public void test_match() {
+ MatchResult result ;
+ s = new Scanner("1 2 ");
+ try {
+ s.match();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+ result = s.match();
+ assertEquals(2, result.start());
+ assertEquals(3, result.end());
+ assertEquals(2, result.start(0));
+ assertEquals(3, result.end(0));
+ assertEquals("2", result.group());
+ assertEquals("2", result.group(0));
+ assertEquals(0, result.groupCount());
+ try {
+ result.start(1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // Expected
+ }
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+ try {
+ s.match();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+
+ s = new Scanner("True faLse");
+ try {
+ s.match();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+ assertTrue(s.nextBoolean());
+ result = s.match();
+ assertEquals(0, result.start());
+ assertEquals(4, result.end());
+ assertEquals(0, result.start(0));
+ assertEquals(4, result.end(0));
+ assertEquals("True", result.group());
+ assertEquals(0, result.groupCount());
+ assertFalse(s.nextBoolean());
+ try {
+ s.nextBoolean();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+ try {
+ s.match();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+
+ s = new Scanner("True faLse");
+ assertTrue(s.nextBoolean());
+ result = s.match();
+ assertEquals(0, result.start());
+ assertEquals(4, result.end());
+ assertEquals(0, result.start(0));
+ assertEquals(4, result.end(0));
+ assertEquals("True", result.group());
+ assertEquals(0, result.groupCount());
+ s.close();
+ try {
+ s.nextBoolean();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+ result = s.match();
+ assertEquals(0, result.start());
+ assertEquals(4, result.end());
+ assertEquals(0, result.start(0));
+ 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
+ }
+ try {
+ s.match();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+
+ s = new Scanner("True fase");
+ assertTrue(s.nextBoolean());
+ try {
+ s.next((Pattern)null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected
+ }
+ result = s.match();
+ assertEquals(0, result.start());
+ assertEquals(4, result.end());
+ assertEquals(0, result.start(0));
+ assertEquals(4, result.end(0));
+ assertEquals("True", result.group());
+ assertEquals(0, result.groupCount());
+
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#next()
+ */
+ public void test_next() throws IOException {
+ // use special delimiter
+ s = new Scanner("1**2").useDelimiter("\\*");
+ assertEquals("1", s.next());
+ assertEquals("", s.next());
+ assertEquals("2", s.next());
+
+ s = new Scanner(" \t 1 \t 2").useDelimiter("\\s*");
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("a").useDelimiter("a?");
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("aa").useDelimiter("a?");
+ assertEquals("", s.next());
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+
+ s = new Scanner("word( )test( )").useDelimiter("\\( \\)");
+ assertEquals("word", s.next());
+ assertEquals("test", s.next());
+
+ s = new Scanner("? next ").useDelimiter("( )");
+ assertEquals("?", s.next());
+ assertEquals("next", s.next());
+ assertEquals("", s.next());
+
+ s = new Scanner("word1 word2 ");
+ assertEquals("word1", s.next());
+ assertEquals("word2", s.next());
+ // test boundary case
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // just delimiter exists in this scanner
+ s = new Scanner(" ");
+ try {
+ s.next();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // nothing exists in this scanner
+ s = new Scanner("");
+ try {
+ s.next();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // no delimiter exists in this scanner
+ s = new Scanner("test");
+ assertEquals("test", s.next());
+
+ // input resourse starts with delimiter
+ s = new Scanner(" test");
+ assertEquals("test", s.next());
+
+ // input resource ends with delimiter
+ s = new Scanner(" test ");
+ assertEquals("test", s.next());
+
+ // Harmony uses 1024 as default buffer size,
+ // What if a sentence can not be read in all in once.
+ StringBuilder longSentence = new StringBuilder(1025);
+ for (int i = 0; i < 11; i++) {
+ longSentence.append(" ");
+ }
+ for (int i = 11; i < 1026; i++) {
+ longSentence.append("a");
+ }
+ s = new Scanner(longSentence.toString());
+ assertEquals(longSentence.toString().trim(), s.next());
+
+ s = new Scanner(" test test");
+ assertEquals("test", s.next());
+ assertEquals("test", s.next());
+
+ // What if use a delimiter of length 0.
+ s = new Scanner("test\ntest").useDelimiter(Pattern.compile("^",
+ 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
+ }
+
+ s = new Scanner("").useDelimiter(Pattern.compile("^*",
+ Pattern.MULTILINE));
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("test\ntest").useDelimiter(Pattern.compile("^*",
+ Pattern.MULTILINE));
+ assertEquals("t", s.next());
+ assertEquals("e", s.next());
+
+ s = new Scanner("\ntest\ntest").useDelimiter(Pattern.compile("$",
+ Pattern.MULTILINE));
+ assertEquals("\ntest", s.next());
+ assertEquals("\ntest", s.next());
+
+ // test socket inputStream
+ // Harmony uses 1024 as default buffer size,
+ // what if the leading delimiter is larger than 1023
+ for (int i = 0; i < 1024; i++) {
+ os.write(" ".getBytes());
+ }
+ os.write(" 1 2 ".getBytes());
+ s = new Scanner(client);
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+ os.write(" 1 2".getBytes());
+ serverSocket.close();
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#next(Pattern)
+ */
+ public void test_nextLPattern() throws IOException {
+ Pattern pattern;
+ s = new Scanner("aab*2*").useDelimiter("\\*");
+ pattern = Pattern.compile("a*b");
+ assertEquals("aab", s.next(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word ? ");
+ pattern = Pattern.compile("\\w+");
+ assertEquals("word", s.next(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word1 word2 ");
+ pattern = Pattern.compile("\\w+");
+ assertEquals("word1", s.next(pattern));
+ assertEquals("word2", s.next(pattern));
+ // test boundary case
+ try {
+ s.next(pattern);
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // test socket inputStream
+
+ os.write("aab 2".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ pattern = Pattern.compile("a*b");
+ assertEquals("aab", s.next(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#next(String)
+ */
+ public void test_nextLString() throws IOException {
+ s = new Scanner("b*a*").useDelimiter("\\*");
+ assertEquals("b", s.next("a*b"));
+ try {
+ s.next("a*b");
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word ? ");
+ assertEquals("word", s.next("\\w+"));
+ try {
+ s.next("\\w+");
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word1 next ");
+ assertEquals("word1", s.next("\\w+"));
+ assertEquals("next", s.next("\\w+"));
+ // test boundary case
+ try {
+ s.next("\\w+");
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // test socket inputStream
+ os.write("aab 2".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ assertEquals("aab", s.next("a*b"));
+ try {
+ s.next("a*b");
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextBoolean()
+ */
+ public void test_nextBoolean() throws IOException {
+ // case insensitive
+ s = new Scanner("TRue");
+ assertTrue(s.nextBoolean());
+
+ s = new Scanner("tRue false");
+ assertTrue(s.nextBoolean());
+ assertFalse(s.nextBoolean());
+ try {
+ s.nextBoolean();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("true1");
+ try {
+ s.nextBoolean();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ try {
+ s = new Scanner("");
+ s.nextBoolean();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // test socket inputStream
+ os.write("true false".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ assertTrue(s.nextBoolean());
+ assertFalse(s.nextBoolean());
+
+ // ues '*' as delimiter
+ s = new Scanner("true**false").useDelimiter("\\*");
+ assertTrue(s.nextBoolean());
+ try {
+ s.nextBoolean();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("false( )").useDelimiter("\\( \\)");
+ assertFalse(s.nextBoolean());
+
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextInt(int)
+ */
+ public void test_nextIntI() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextInt(10));
+ assertEquals(456, s.nextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertEquals(38, s.nextInt(5));
+ try {
+ s.nextInt(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt(10));
+ assertEquals(23456, s.nextInt(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt(10));
+ assertEquals(23456, s.nextInt(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextInt(10));
+ try {
+ s.nextInt(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertEquals(162, s.nextInt(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt(10));
+ assertEquals(23456, s.nextInt(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextInt(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextInt(10));
+
+ s = new Scanner("E3456");
+ assertEquals(930902, s.nextInt(16));
+ // The following test case fails on RI, because RI does not support
+ // letter as leading digit
+ s = new Scanner("E3,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(930902, s.nextInt(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextInt(10));
+
+ 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));
+
+ /*
+ * 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
+ * exclusively.
+ */
+
+ /*
+ * 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
+ * by scanner with locale mk_MK. But this is not the case on RI.
+ */
+ s = new Scanner("-123 123- -123-");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(-123, s.nextInt(10));
+ // The following test case fails on RI
+ assertEquals(-123, s.nextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("-123 123-");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(-123, s.nextInt(10));
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ // Skip the un-recognizable token 123-.
+ assertEquals("123-", s.next());
+
+ // If the parameter radix is illegal, the following test cases fail on
+ // RI
+ try {
+ s.nextInt(Character.MIN_RADIX - 1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ try {
+ s.nextInt(Character.MAX_RADIX + 1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextInt()
+ */
+ public void test_nextInt() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextInt());
+ assertEquals(456, s.nextInt());
+ try {
+ s.nextInt();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertEquals(38, s.nextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt());
+ assertEquals(23456, s.nextInt());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt());
+ assertEquals(23456, s.nextInt());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextInt());
+ s.useRadix(5);
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertEquals(162, s.nextInt());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextInt());
+ assertEquals(23456, s.nextInt());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextInt());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextInt());
+
+ s = new Scanner("E3456");
+ s.useRadix(16);
+ assertEquals(930902, s.nextInt());
+
+ // The following test case fails on RI, because RI does not support
+ // letter as leading digit
+ s = new Scanner("E3,456");
+ s.useLocale(Locale.ENGLISH);
+ s.useRadix(16);
+ assertEquals(930902, s.nextInt());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextInt());
+
+ 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());
+
+ /*
+ * 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
+ * exclusively.
+ */
+
+ /*
+ * 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
+ * by scanner with locale mk_MK. But this is not the case on RI.
+ */
+ s = new Scanner("-123 123- -123-");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(-123, s.nextInt());
+ // The following test case fails on RI
+ assertEquals(-123, s.nextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("-123 123-");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(-123, s.nextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ // Skip the un-recognizable token 123-.
+ assertEquals("123-", s.next());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextByte(int)
+ */
+ public void test_nextByteI() throws IOException {
+ s = new Scanner("123 126");
+ assertEquals(123, s.nextByte(10));
+ assertEquals(126, s.nextByte(10));
+ try {
+ s.nextByte(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 126");
+ assertEquals(38, s.nextByte(5));
+ try {
+ s.nextByte(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("1234");
+ try {
+ s.nextByte(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 12\u0666");
+ assertEquals(102, s.nextByte(10));
+ try {
+ s.nextByte(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertEquals(126, s.nextByte(10));
+
+ s = new Scanner("012");
+ assertEquals(12, s.nextByte(10));
+
+ s = new Scanner("E");
+ assertEquals(14, s.nextByte(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("100");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(100, s.nextByte(10));
+
+ 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));
+
+ 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"));
+ assertEquals(-123, s.nextByte(10));
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextByte()
+ */
+ public void test_nextByte() throws IOException {
+ s = new Scanner("123 126");
+ assertEquals(123, s.nextByte());
+ assertEquals(126, s.nextByte());
+ try {
+ s.nextByte();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 126");
+ s.useRadix(5);
+ assertEquals(38, s.nextByte());
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("1234");
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 12\u0666");
+ assertEquals(102, s.nextByte());
+ s.useRadix(5);
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertEquals(126, s.nextByte());
+
+ s = new Scanner("012");
+ assertEquals(12, s.nextByte());
+
+ s = new Scanner("E");
+ s.useRadix(16);
+ assertEquals(14, s.nextByte());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("100");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(100, s.nextByte());
+
+ 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());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(-123, s.nextByte());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(-123, s.nextByte());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextFloat()
+ */
+ public void test_nextFloat() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)123.0, s.nextFloat());
+ assertEquals((float)456.0, s.nextFloat());
+ assertEquals((float)123.4, s.nextFloat());
+ assertEquals((float)0.123, s.nextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)123.4, s.nextFloat());
+ assertEquals((float)-456.7, s.nextFloat());
+ assertEquals((float)123456.789, s.nextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)1.234E12, s.nextFloat());
+ assertEquals((float)-4.567E14, s.nextFloat());
+ assertEquals((float)1.23456789E-5, s.nextFloat());
+
+ s = new Scanner("NaN Infinity -Infinity");
+ assertEquals(Float.NaN, s.nextFloat());
+ assertEquals(Float.POSITIVE_INFINITY, s.nextFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, s.nextFloat());
+
+ 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.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)23456.0, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertEquals((float)23.456, s.nextFloat());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)23.456, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertEquals((float)23456.0, s.nextFloat());
+
+ s = new Scanner("23,456.7 23.456,7");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals((float)23456.7, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertEquals((float)23456.7, s.nextFloat());
+
+ s = new Scanner("-123.4 123.4- -123.4-");
+ s.useLocale(new Locale("ar", "AE"));
+ // FIXME
+// assertEquals((float)-123.4, s.nextFloat());
+// //The following test case fails on RI
+// assertEquals((float)-123.4, s.nextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("123- -123");
+ s.useLocale(new Locale("mk", "MK"));
+ try {
+ s.nextFloat();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // 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)
+ */
+ public void test_nextBigIntegerI() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(new BigInteger("123"), s.nextBigInteger(10));
+ assertEquals(new BigInteger("456"), s.nextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertEquals(new BigInteger("38"), s.nextBigInteger(5));
+ try {
+ s.nextBigInteger(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(new BigInteger("102"), s.nextBigInteger(10));
+ try {
+ s.nextBigInteger(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertEquals(new BigInteger("162"), s.nextBigInteger(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+ s = new Scanner("E34");
+ assertEquals(new BigInteger("3636"), s.nextBigInteger(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+ 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));
+
+ 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"));
+ assertEquals(new BigInteger("-123"), s.nextBigInteger(10));
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextBigInteger()
+ */
+ public void test_nextBigInteger() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(new BigInteger("123"), s.nextBigInteger());
+ assertEquals(new BigInteger("456"), s.nextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertEquals(new BigInteger("38"), s.nextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(new BigInteger("102"), s.nextBigInteger());
+ s.useRadix(5);
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertEquals(new BigInteger("162"), s.nextBigInteger());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertEquals(new BigInteger("3636"), s.nextBigInteger());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+ 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());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(new BigInteger("-123"), s.nextBigInteger());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(new BigInteger("-123"), s.nextBigInteger());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextShort(int)
+ */
+ public void test_nextShortI() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextShort(10));
+ assertEquals(456, s.nextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertEquals(38, s.nextShort(5));
+ try {
+ s.nextShort(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789");
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort(10));
+ assertEquals(23456, s.nextShort(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort(10));
+ assertEquals(23456, s.nextShort(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextShort(10));
+ try {
+ s.nextShort(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertEquals(162, s.nextShort(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort(10));
+ assertEquals(23456, s.nextShort(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextShort(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextShort(10));
+
+ s = new Scanner("E34");
+ assertEquals(3636, s.nextShort(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextShort(10));
+
+ 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));
+
+ 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"));
+ assertEquals(-123, s.nextShort(10));
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextShort()
+ */
+ public void test_nextShort() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextShort());
+ assertEquals(456, s.nextShort());
+ try {
+ s.nextShort();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertEquals(38, s.nextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789");
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort());
+ assertEquals(23456, s.nextShort());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort());
+ assertEquals(23456, s.nextShort());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextShort());
+ s.useRadix(5);
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertEquals(162, s.nextShort());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextShort());
+ assertEquals(23456, s.nextShort());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextShort());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextShort());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertEquals(3636, s.nextShort());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextShort());
+
+ 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());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(-123, s.nextShort());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(-123, s.nextShort());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextLong(int)
+ */
+ public void test_nextLongI() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextLong(10));
+ assertEquals(456, s.nextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertEquals(38, s.nextLong(5));
+ try {
+ s.nextLong(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextLong(10));
+ try {
+ s.nextLong(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertEquals(162, s.nextLong(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextLong(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextLong(10));
+
+ s = new Scanner("E34");
+ assertEquals(3636, s.nextLong(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextLong(10));
+
+ 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));
+
+ 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()
+ */
+ public void test_nextLong() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextLong());
+ assertEquals(456, s.nextLong());
+ try {
+ s.nextLong();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertEquals(38, s.nextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong());
+ assertEquals(23456, s.nextLong());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong());
+ assertEquals(23456, s.nextLong());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextLong());
+ s.useRadix(5);
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertEquals(162, s.nextLong());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertEquals(23456, s.nextLong());
+ assertEquals(23456, s.nextLong());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertEquals(3456, s.nextLong());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextLong());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertEquals(3636, s.nextLong());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertEquals(12300, s.nextLong());
+
+ 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());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertEquals(-123, s.nextLong());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertEquals(-123, s.nextLong());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNext()
+ */
+ public void test_hasNext() throws IOException {
+ s = new Scanner("1##2").useDelimiter("\\#");
+ assertTrue(s.hasNext());
+ assertEquals("1", s.next());
+ assertEquals("", s.next());
+ assertEquals("2", s.next());
+ assertFalse(s.hasNext());
+ s.close();
+ try {
+ s.hasNext();
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("1( )2( )").useDelimiter("\\( \\)");
+ assertTrue(s.hasNext());
+ assertTrue(s.hasNext());
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+
+ s = new Scanner("1 2 ").useDelimiter("( )");
+ assertEquals("1", s.next());
+ assertEquals("2", s.next());
+ assertTrue(s.hasNext());
+ assertEquals("", s.next());
+
+ s = new Scanner("1\n2 ");
+ assertEquals("1", s.next());
+ assertTrue(s.hasNext());
+ assertEquals("2", s.next());
+ assertFalse(s.hasNext());
+ // test boundary case
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("1'\n'2 ");
+ assertEquals("1'", s.next());
+ assertTrue(s.hasNext());
+ assertEquals("'2", s.next());
+ assertFalse(s.hasNext());
+ // test boundary case
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner(" ");
+ assertFalse(s.hasNext());
+
+ // test socket inputStream
+
+ os.write("1 2".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ assertEquals("1", s.next());
+ assertTrue(s.hasNext());
+ assertEquals("2", s.next());
+ assertFalse(s.hasNext());
+ try {
+ s.next();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNext(Pattern)
+ */
+ public void test_hasNextLPattern() throws IOException {
+ Pattern pattern;
+ s = new Scanner("aab@2@abb@").useDelimiter("\\@");
+ pattern = Pattern.compile("a*b");
+ assertTrue(s.hasNext(pattern));
+ assertEquals("aab", s.next(pattern));
+ assertFalse(s.hasNext(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word ? ");
+ pattern = Pattern.compile("\\w+");
+ assertTrue(s.hasNext(pattern));
+ assertEquals("word", s.next(pattern));
+ assertFalse(s.hasNext(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word1 WorD2 ");
+ pattern = Pattern.compile("\\w+");
+ assertTrue(s.hasNext(pattern));
+ assertEquals("word1", s.next(pattern));
+ assertTrue(s.hasNext(pattern));
+ assertEquals("WorD2", s.next(pattern));
+ assertFalse(s.hasNext(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("word1 WorD2 ");
+ pattern = Pattern.compile("\\w+");
+ try {
+ s.hasNext((Pattern) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ s.close();
+ try {
+ s.hasNext(pattern);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ // test socket inputStream
+ os.write("aab b".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ pattern = Pattern.compile("a+b");
+ assertTrue(s.hasNext(pattern));
+ assertEquals("aab", s.next(pattern));
+ assertFalse(s.hasNext(pattern));
+ try {
+ s.next(pattern);
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNext(String)
+ */
+ public void test_hasNextLString() throws IOException {
+ s = new Scanner("aab@2@abb@").useDelimiter("\\@");
+ try {
+ s.hasNext((String)null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // 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
+ }
+ s.close();
+ try {
+ s.hasNext("a+b");
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("WORD ? ");
+ assertTrue(s.hasNext("\\w+"));
+ assertEquals("WORD", s.next("\\w+"));
+ assertFalse(s.hasNext("\\w+"));
+ try {
+ s.next("\\w+");
+ fail("should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("word1 word2 ");
+ assertEquals("word1", s.next("\\w+"));
+ assertEquals("word2", s.next("\\w+"));
+ // test boundary case
+ try {
+ s.next("\\w+");
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // test socket inputStream
+
+ os.write("aab 2".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ 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
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextBoolean()
+ */
+ public void test_hasNextBoolean() throws IOException {
+
+ s = new Scanner("TRue");
+ assertTrue(s.hasNextBoolean());
+ assertTrue(s.nextBoolean());
+
+ s = new Scanner("tRue false");
+ assertTrue(s.hasNextBoolean());
+ assertTrue(s.nextBoolean());
+ assertTrue(s.hasNextBoolean());
+ assertFalse(s.nextBoolean());
+
+ s = new Scanner("");
+ assertFalse(s.hasNextBoolean());
+
+ // test socket inputStream
+
+ os.write("true false ".getBytes());
+ serverSocket.close();
+
+ s = new Scanner(client);
+ assertTrue(s.hasNextBoolean());
+ assertTrue(s.nextBoolean());
+
+ // ues '*' as delimiter
+ s = new Scanner("true**false").useDelimiter("\\*");
+ assertTrue(s.hasNextBoolean());
+ assertTrue(s.nextBoolean());
+ assertFalse(s.hasNextBoolean());
+ try {
+ s.nextBoolean();
+ fail("should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("false( )").useDelimiter("\\( \\)");
+ assertTrue(s.hasNextBoolean());
+ assertFalse(s.nextBoolean());
+ assertFalse(s.hasNextBoolean());
+
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextByte(int)
+ */
+ public void test_hasNextByteI() throws IOException {
+ s = new Scanner("123 126");
+ assertTrue(s.hasNextByte(10));
+ assertEquals(123, s.nextByte(10));
+ assertTrue(s.hasNextByte(10));
+ assertEquals(126, s.nextByte(10));
+ assertFalse(s.hasNextByte(10));
+ try {
+ s.nextByte(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 126");
+ assertTrue(s.hasNextByte(5));
+ assertEquals(38, s.nextByte(5));
+ assertFalse(s.hasNextByte(5));
+ try {
+ s.nextByte(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("1234");
+ assertFalse(s.hasNextByte(10));
+ try {
+ s.nextByte(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 12\u0666");
+ assertTrue(s.hasNextByte(10));
+ assertEquals(102, s.nextByte(10));
+ assertFalse(s.hasNextByte(5));
+ try {
+ s.nextByte(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertTrue(s.hasNextByte(10));
+ assertEquals(126, s.nextByte(10));
+
+ s = new Scanner("012");
+ assertTrue(s.hasNextByte(10));
+ assertEquals(12, s.nextByte(10));
+
+ s = new Scanner("E");
+ assertTrue(s.hasNextByte(16));
+ assertEquals(14, s.nextByte(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("100");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextByte(10));
+ assertEquals(100, s.nextByte(10));
+
+ s = new Scanner("1\u0966\u0966");
+ 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));
+ assertEquals(100, s.nextByte(10));
+
+ s = new Scanner("-123");
+ 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"));
+ assertTrue(s.hasNextByte(10));
+ 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(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
+ }
+ }
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextByte()
+ */
+ public void test_hasNextByte() throws IOException {
+ s = new Scanner("123 126");
+ assertTrue(s.hasNextByte());
+ assertEquals(123, s.nextByte());
+ assertTrue(s.hasNextByte());
+ assertEquals(126, s.nextByte());
+ assertFalse(s.hasNextByte());
+ try {
+ s.nextByte();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 126");
+ s.useRadix(5);
+ assertTrue(s.hasNextByte());
+ assertEquals(38, s.nextByte());
+ assertFalse(s.hasNextByte());
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("1234");
+ assertFalse(s.hasNextByte());
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 12\u0666");
+ assertTrue(s.hasNextByte());
+ assertEquals(102, s.nextByte());
+ s.useRadix(5);
+ assertFalse(s.hasNextByte());
+ try {
+ s.nextByte();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertTrue(s.hasNextByte());
+ assertEquals(126, s.nextByte());
+
+ s = new Scanner("012");
+ assertEquals(12, s.nextByte());
+
+ s = new Scanner("E");
+ s.useRadix(16);
+ assertTrue(s.hasNextByte());
+ assertEquals(14, s.nextByte());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("100");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextByte());
+ assertEquals(100, s.nextByte());
+
+ s = new Scanner("1\u0966\u0966");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextByte());
+ assertEquals(100, s.nextByte());
+
+ s = new Scanner("1\u0e50\u0e50");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextByte());
+ assertEquals(100, s.nextByte());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextByte());
+ assertEquals(-123, s.nextByte());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextByte());
+ assertEquals(-123, s.nextByte());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextBigInteger(int)
+ */
+ public void test_hasNextBigIntegerI() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("123"), s.nextBigInteger(10));
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("456"), s.nextBigInteger(10));
+ assertFalse(s.hasNextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextBigInteger(5));
+ assertEquals(new BigInteger("38"), s.nextBigInteger(5));
+ assertFalse(s.hasNextBigInteger(5));
+ try {
+ s.nextBigInteger(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("102"), s.nextBigInteger(10));
+ assertFalse(s.hasNextBigInteger(5));
+ try {
+ s.nextBigInteger(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("162"), s.nextBigInteger(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("23456"), s.nextBigInteger(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextBigInteger(10));
+ try {
+ s.nextBigInteger(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("3456"), s.nextBigInteger(10));
+
+ s = new Scanner("E34");
+ assertTrue(s.hasNextBigInteger(16));
+ assertEquals(new BigInteger("3636"), s.nextBigInteger(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextBigInteger(10));
+ assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+ s = new Scanner("123\u0966\u0966");
+ 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));
+ assertEquals(new BigInteger("12300"), s.nextBigInteger(10));
+
+ s = new Scanner("-123");
+ 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("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
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextBigInteger()
+ */
+ public void test_hasNextBigInteger() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("123"), s.nextBigInteger());
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("456"), s.nextBigInteger());
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("38"), s.nextBigInteger());
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(new BigInteger("102"), s.nextBigInteger());
+ s.useRadix(5);
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("162"), s.nextBigInteger());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("23456"), s.nextBigInteger());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextBigInteger());
+ try {
+ s.nextBigInteger();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("3456"), s.nextBigInteger());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("3636"), s.nextBigInteger());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+ s = new Scanner("123\u0966\u0966");
+ 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());
+ assertEquals(new BigInteger("12300"), s.nextBigInteger());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("-123"), s.nextBigInteger());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextBigInteger());
+ assertEquals(new BigInteger("-123"), s.nextBigInteger());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextInt(int)
+ */
+ public void test_hasNextIntI() throws IOException {
+ s = new Scanner("123 456");
+ assertEquals(123, s.nextInt(10));
+ assertTrue(s.hasNextInt(10));
+ assertEquals(456, s.nextInt(10));
+ assertFalse(s.hasNextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextInt(5));
+ assertEquals(38, s.nextInt(5));
+ assertFalse(s.hasNextInt(5));
+ try {
+ s.nextInt(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ assertFalse(s.hasNextInt(10));
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextInt(10));
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextInt(10));
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextInt(10));
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextInt(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06662");
+ assertTrue(s.hasNextInt(10));
+ assertFalse(s.hasNextInt(5));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextInt(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextInt(10));
+ assertEquals(3456, s.nextInt(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextInt(10));
+ assertEquals(3456, s.nextInt(10));
+
+ s = new Scanner("E3456");
+ assertTrue(s.hasNextInt(16));
+ assertEquals(930902, s.nextInt(16));
+ // The following test case fails on RI, because RI does not support
+ // letter as leading digit
+ s = new Scanner("E3,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextInt(16));
+ assertEquals(930902, s.nextInt(16));
+
+ // 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
+ }
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt(10));
+ assertEquals(12300, s.nextInt(10));
+
+ s = new Scanner("123\u0966\u0966");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt(10));
+ assertEquals(12300, s.nextInt(10));
+
+ s = new Scanner("123\u0e50\u0e50");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt(10));
+ assertEquals(12300, s.nextInt(10));
+
+ /*
+ * 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
+ * exclusively.
+ */
+
+ /*
+ * 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
+ * by scanner with locale mk_MK. But this is not the case on RI.
+ */
+ s = new Scanner("-123 123- -123-");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextInt(10));
+ assertEquals(-123, s.nextInt(10));
+ // The following test case fails on RI
+ assertTrue(s.hasNextInt(10));
+ assertEquals(-123, s.nextInt(10));
+ assertFalse(s.hasNextInt(10));
+ try {
+ s.nextInt(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("-123 123-");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextInt(10));
+ assertEquals(-123, s.nextInt(10));
+ assertFalse(s.hasNextInt(10));
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ // Skip the un-recognizable token 123-.
+ assertEquals("123-", s.next());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextInt(int)
+ */
+ 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));
+ 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
+ }
+ }
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextInt()
+ */
+ public void test_hasNextInt() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextInt());
+ assertEquals(123, s.nextInt());
+ assertEquals(456, s.nextInt());
+ assertFalse(s.hasNextInt());
+ try {
+ s.nextInt();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertTrue(s.hasNextInt());
+ assertEquals(38, s.nextInt());
+ assertFalse(s.hasNextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ assertFalse(s.hasNextInt());
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextInt());
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextInt());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextInt());
+ s.useLocale(new Locale("it", "CH"));
+ assertTrue(s.hasNextInt());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06662");
+ s.useRadix(5);
+ assertFalse(s.hasNextInt());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextInt());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextInt());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextInt());
+ assertEquals(3456, s.nextInt());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(3456, s.nextInt());
+
+ s = new Scanner("E3456");
+ s.useRadix(16);
+ assertTrue(s.hasNextInt());
+ assertEquals(930902, s.nextInt());
+
+ // The following test case fails on RI, because RI does not support
+ // letter as leading digit
+ s = new Scanner("E3,456");
+ s.useLocale(Locale.ENGLISH);
+ s.useRadix(16);
+ assertTrue(s.hasNextInt());
+ assertEquals(930902, s.nextInt());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt());
+ assertEquals(12300, s.nextInt());
+
+ s = new Scanner("123\u0966\u0966");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt());
+ assertEquals(12300, s.nextInt());
+
+ s = new Scanner("123\u0e50\u0e50");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextInt());
+ assertEquals(12300, s.nextInt());
+
+ /*
+ * 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
+ * exclusively.
+ */
+
+ /*
+ * 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
+ * by scanner with locale mk_MK. But this is not the case on RI.
+ */
+ s = new Scanner("-123 123- -123-");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextInt());
+ assertEquals(-123, s.nextInt());
+ // The following test case fails on RI
+ assertTrue(s.hasNextInt());
+ assertEquals(-123, s.nextInt());
+ assertFalse(s.hasNextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+
+ s = new Scanner("-123 123-");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextInt());
+ assertEquals(-123, s.nextInt());
+ try {
+ s.nextInt();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // expected
+ }
+ // Skip the un-recognizable token 123-.
+ assertEquals("123-", s.next());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextFloat()
+ */
+ public void test_hasNextFloat() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)123.0, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)456.0, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)123.4, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)0.123, s.nextFloat());
+ assertFalse(s.hasNextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)123.4, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)-456.7, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)123456.789, s.nextFloat());
+ assertFalse(s.hasNextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)1.234E12, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)-4.567E14, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)1.23456789E-5, s.nextFloat());
+
+ s = new Scanner("NaN Infinity -Infinity");
+ assertTrue(s.hasNextFloat());
+ assertEquals(Float.NaN, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals(Float.POSITIVE_INFINITY, s.nextFloat());
+ assertTrue(s.hasNextFloat());
+ assertEquals(Float.NEGATIVE_INFINITY, s.nextFloat());
+
+ String str=String.valueOf(Float.MAX_VALUE*2);
+ 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.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23456.0, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23.456, s.nextFloat());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23.456, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23456.0, s.nextFloat());
+
+ s = new Scanner("23,456.7 23.456,7");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23456.7, s.nextFloat());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextFloat());
+ assertEquals((float)23456.7, s.nextFloat());
+
+ //FIXME
+// s = new Scanner("-123.4 123.4- -123.4-");
+// s.useLocale(new Locale("ar", "AE"));
+// assertTrue(s.hasNextFloat());
+// assertEquals((float)-123.4, s.nextFloat());
+// //The following test case fails on RI
+// assertTrue(s.hasNextFloat());
+// assertEquals((float)-123.4, s.nextFloat());
+// try {
+// s.nextFloat();
+// fail("Should throw InputMismatchException");
+// } catch (InputMismatchException e) {
+// // Expected
+// }
+
+ s = new Scanner("123- -123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertFalse(s.hasNextFloat());
+ try {
+ s.nextFloat();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // 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
+ }
+
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextShort(int)
+ */
+ public void test_hasNextShortI() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort(10));
+ assertEquals(123, s.nextShort(10));
+ assertTrue(s.hasNextShort(10));
+ assertEquals(456, s.nextShort(10));
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort(5));
+ assertEquals(38, s.nextShort(5));
+ assertFalse(s.hasNextShort(5));
+ try {
+ s.nextShort(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789");
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextInt(10));
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextInt(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextShort(10));
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextShort(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertTrue(s.hasNextShort(10));
+ assertEquals(102, s.nextShort(10));
+ assertFalse(s.hasNextShort(5));
+ try {
+ s.nextShort(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertTrue(s.hasNextShort(10));
+ assertEquals(162, s.nextShort(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextShort(10));
+ assertTrue(s.hasNextShort(10));
+ assertEquals(23456, s.nextShort(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextShort(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextShort(10));
+ assertEquals(3456, s.nextShort(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextShort(10));
+ assertEquals(3456, s.nextShort(10));
+
+ s = new Scanner("E34");
+ assertTrue(s.hasNextShort(16));
+ assertEquals(3636, s.nextShort(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextShort(10));
+ assertEquals(12300, s.nextShort(10));
+
+ s = new Scanner("123\u0966\u0966");
+ 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));
+ assertEquals(12300, s.nextShort(10));
+
+ s = new Scanner("-123");
+ 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"));
+ assertTrue(s.hasNextShort(10));
+ assertEquals(-123, s.nextShort(10));
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextShort()
+ */
+ public void test_hasNextShort() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextShort());
+ assertEquals(123, s.nextShort());
+ assertTrue(s.hasNextShort());
+ assertEquals(456, s.nextShort());
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertTrue(s.hasNextShort());
+ assertEquals(38, s.nextShort());
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789");
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextShort());
+ s.useRadix(5);
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertTrue(s.hasNextShort());
+ assertEquals(162, s.nextShort());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+ assertTrue(s.hasNextShort());
+ assertEquals(23456, s.nextShort());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextShort());
+ try {
+ s.nextShort();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextShort());
+ assertEquals(3456, s.nextShort());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextShort());
+ assertEquals(3456, s.nextShort());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertTrue(s.hasNextShort());
+ assertEquals(3636, s.nextShort());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextShort());
+ assertEquals(12300, s.nextShort());
+
+ s = new Scanner("123\u0966\u0966");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextShort());
+ assertEquals(12300, s.nextShort());
+
+ s = new Scanner("123\u0e50\u0e50");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextShort());
+ assertEquals(12300, s.nextShort());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextShort());
+ assertEquals(-123, s.nextShort());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextShort());
+ assertEquals(-123, s.nextShort());
+ }
+
+ /**
+ * @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));
+ 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
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextLong(int)
+ */
+ public void test_hasNextLongI() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong(10));
+ assertEquals(123, s.nextLong(10));
+ assertTrue(s.hasNextLong(10));
+ assertEquals(456, s.nextLong(10));
+ assertFalse(s.hasNextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong(5));
+ assertEquals(38, s.nextLong(5));
+ assertFalse(s.hasNextLong(5));
+ try {
+ s.nextLong(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ assertFalse(s.hasNextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextShort(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertTrue(s.hasNextLong(10));
+ assertEquals(102, s.nextLong(10));
+ assertFalse(s.hasNextLong(5));
+ try {
+ s.nextLong(5);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ assertTrue(s.hasNextLong(10));
+ assertEquals(162, s.nextLong(10));
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+ assertTrue(s.hasNextLong(10));
+ assertEquals(23456, s.nextLong(10));
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextLong(10));
+ try {
+ s.nextLong(10);
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextLong(10));
+ assertEquals(3456, s.nextLong(10));
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextLong(10));
+ assertEquals(3456, s.nextLong(10));
+
+ s = new Scanner("E34");
+ assertTrue(s.hasNextLong(16));
+ assertEquals(3636, s.nextLong(16));
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextLong(10));
+ assertEquals(12300, s.nextLong(10));
+
+ s = new Scanner("123\u0966\u0966");
+ 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));
+ assertEquals(12300, s.nextLong(10));
+
+ s = new Scanner("-123");
+ 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)
+ */
+ 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));
+ 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
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextLong()
+ */
+ public void test_hasNextLong() throws IOException {
+ s = new Scanner("123 456");
+ assertTrue(s.hasNextLong());
+ assertEquals(123, s.nextLong());
+ assertTrue(s.hasNextLong());
+ assertEquals(456, s.nextLong());
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ // If the radix is different from 10
+ s = new Scanner("123 456");
+ s.useRadix(5);
+ assertTrue(s.hasNextLong());
+ assertEquals(38, s.nextLong());
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // If the number is out of range
+ s = new Scanner("123456789123456789123456789123456789");
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.ENGLISH);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+
+ /*
+ * ''' is used in many locales as group separator.
+ */
+ s = new Scanner("23'456 23'456");
+ s.useLocale(Locale.GERMANY);
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(new Locale("it", "CH"));
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+
+ /*
+ * The input string has Arabic-Indic digits.
+ */
+ s = new Scanner("1\u06602 1\u06662");
+ assertEquals(102, s.nextLong());
+ s.useRadix(5);
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useRadix(10);
+ assertTrue(s.hasNextLong());
+ assertEquals(162, s.nextLong());
+
+ /*
+ * '.' is used in many locales as group separator. The input string
+ * has Arabic-Indic digits .
+ */
+ s = new Scanner("23.45\u0666 23.456");
+ s.useLocale(Locale.CHINESE);
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+ s.useLocale(Locale.GERMANY);
+ // If exception is thrown out, input will not be advanced.
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+ assertTrue(s.hasNextLong());
+ assertEquals(23456, s.nextLong());
+
+ // The input string starts with zero
+ s = new Scanner("03,456");
+ s.useLocale(Locale.ENGLISH);
+ assertFalse(s.hasNextLong());
+ try {
+ s.nextLong();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ s = new Scanner("03456");
+ assertTrue(s.hasNextLong());
+ assertEquals(3456, s.nextLong());
+
+ s = new Scanner("\u06603,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextLong());
+ assertEquals(3456, s.nextLong());
+
+ s = new Scanner("E34");
+ s.useRadix(16);
+ assertTrue(s.hasNextLong());
+ assertEquals(3636, s.nextLong());
+
+ /*
+ * There are 3 types of zero digit in all locales, '0' '\u0966' '\u0e50'
+ * respectively, but they are not differentiated.
+ */
+ s = new Scanner("12300");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextLong());
+ assertEquals(12300, s.nextLong());
+
+ s = new Scanner("123\u0966\u0966");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextLong());
+ assertEquals(12300, s.nextLong());
+
+ s = new Scanner("123\u0e50\u0e50");
+ s.useLocale(Locale.CHINESE);
+ assertTrue(s.hasNextLong());
+ assertEquals(12300, s.nextLong());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("ar", "AE"));
+ assertTrue(s.hasNextLong());
+ assertEquals(-123, s.nextLong());
+
+ s = new Scanner("-123");
+ s.useLocale(new Locale("mk", "MK"));
+ assertTrue(s.hasNextLong());
+ assertEquals(-123, s.nextLong());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextDouble()
+ */
+ public void test_hasNextDouble() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(123.0, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(456.0, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(123.4, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(0.123, s.nextDouble());
+ assertFalse(s.hasNextDouble());
+ try {
+ s.nextDouble();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(123.4, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(-456.7, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(123456.789, s.nextDouble());
+ assertFalse(s.hasNextDouble());
+ try {
+ s.nextDouble();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(1.234E12, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(-4.567E14, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(1.23456789E-5, s.nextDouble());
+
+ s = new Scanner("NaN Infinity -Infinity");
+ assertTrue(s.hasNextDouble());
+ assertEquals(Double.NaN, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
+ assertTrue(s.hasNextDouble());
+ assertEquals(Double.NEGATIVE_INFINITY, s.nextDouble());
+
+ String str=String.valueOf(Double.MAX_VALUE*2);
+ 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.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23456.0, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23.456, s.nextDouble());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23.456, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23456.0, s.nextDouble());
+
+ s = new Scanner("23,456.7 23.456,7");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23456.7, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextDouble());
+ assertEquals(23456.7, s.nextDouble());
+
+ s = new Scanner("-123.4");
+ 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
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#hasNextBigDecimal()
+ */
+ public void test_hasNextBigDecimal() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("123"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("456"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("0.123"), s.nextBigDecimal());
+ assertFalse(s.hasNextBigDecimal());
+ try {
+ s.nextBigDecimal();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("-456.7"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("123456.789"), s.nextBigDecimal());
+ assertFalse(s.hasNextBigDecimal());
+ try {
+ s.nextBigDecimal();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("1.234E12"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("-4.567E14"), s.nextBigDecimal());
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("1.23456789E-5"), s.nextBigDecimal());
+
+ s = new Scanner("NaN");
+ assertFalse(s.hasNextBigDecimal());
+ try {
+ s.nextBigDecimal();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+ s.useLocale(Locale.GERMANY);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+
+ s = new Scanner("23,456.7");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("23456.7"), s.nextBigDecimal());
+
+ s = new Scanner("-123.4");
+ s.useLocale(Locale.ENGLISH);
+ assertTrue(s.hasNextBigDecimal());
+ assertEquals(new BigDecimal("-123.4"), s.nextBigDecimal());
+ }
+
+ 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();
+ }
+
+ }
+
+ private static class MockStringReader2Read extends StringReader {
+ private int timesRead = 1;
+
+ public MockStringReader2Read(String param) {
+ super(param);
+ }
+
+ public int read(CharBuffer target) throws IOException {
+ if (timesRead == 1) {
+ target.append('1');
+ target.append('2');
+ target.append('3');
+ timesRead++;
+ return 3;
+ } else if (timesRead == 2) {
+ target.append('t');
+ timesRead++;
+ return 1;
+ } else {
+ throw new IOException();
+ }
+ }
+
+ }
+
+ /**
+ * @tests java.util.Scanner#findWithinHorizon(Pattern, int)
+ */
+ public void test_findWithinHorizon_LPatternI(){
+
+ // This method searches through the input up to the specified search
+ // horizon(exclusive).
+ s = new Scanner("123test");
+ String result = s.findWithinHorizon(Pattern.compile("\\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(Pattern.compile("\\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(Pattern.compile("\\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(Pattern.compile("\\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(Pattern.compile("\\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((Pattern) null, -1);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ s.findWithinHorizon(Pattern.compile("\\p{Digit}+"), -1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ s.close();
+ try {
+ s.findWithinHorizon((Pattern) null, -1);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("test");
+ result = s.findWithinHorizon(Pattern.compile("\\w+"), 10);
+ 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);
+ assertNull(result);
+
+ try {
+ mresult = s.match();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("");
+ result = s.findWithinHorizon(Pattern.compile("^"), 0);
+ assertEquals("", result);
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(0, matchResult.end());
+
+ result = s.findWithinHorizon(Pattern.compile("$"), 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(Pattern
+ .compile("(\\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(Pattern
+ .compile("(\\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(Pattern.compile("test"), 1);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("word1 WorD2 ");
+ s.close();
+ try {
+ s.findWithinHorizon(Pattern.compile("\\d+"), 10);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("word1 WorD2 wOrd3 ");
+ Pattern pattern = Pattern.compile("\\d+");
+ assertEquals("1", s.findWithinHorizon(pattern, 10));
+ assertEquals("WorD2", s.next());
+ assertEquals("3", s.findWithinHorizon(pattern, 15));
+
+ // Regression test
+ s = new Scanner(new MockStringReader("MockStringReader"));
+ pattern = Pattern.compile("test");
+ result = s.findWithinHorizon(pattern, 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());
+ pattern = Pattern.compile("\\p{Lower}+");
+ result = s.findWithinHorizon(pattern, 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());
+ pattern = Pattern.compile("\\p{Lower}+");
+ result = s.findWithinHorizon(pattern, 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());
+ pattern = Pattern.compile("bbc");
+ result = s.findWithinHorizon(pattern, 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());
+ 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('-');
+ }
+ stringBuilder.replace(0, 2, "aa");
+ 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)
+ */
+ public void test_findInLine_LPattern() {
+
+ Scanner s = new Scanner("");
+ try {
+ s.findInLine((Pattern) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // Expected
+ }
+ String result = s.findInLine(Pattern.compile("^"));
+ assertEquals("", result);
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(0, matchResult.end());
+
+ result = s.findInLine(Pattern.compile("$"));
+ 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(Pattern.compile("a\nb*"));
+ assertNull(result);
+
+ s = new Scanner("aa\nbb.b");
+ result = s.findInLine(Pattern.compile("\\."));
+ assertNull(result);
+
+ s = new Scanner("abcd1234test\n");
+ result = s.findInLine(Pattern.compile("\\p{Lower}+"));
+ assertEquals("abcd", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ result = s.findInLine(Pattern.compile("\\p{Digit}{5}"));
+ assertNull(result);
+ try {
+ matchResult = s.match();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ result = s.findInLine(Pattern.compile("\\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(Pattern.compile("\\p{Digit}+"));
+ assertEquals("1234", result);
+ matchResult = s.match();
+ assertEquals(2048, matchResult.start());
+ assertEquals(2052, matchResult.end());
+
+ s = new Scanner("test");
+ s.close();
+ try {
+ s.findInLine((Pattern) null);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("test1234\n1234 test");
+ result = s.findInLine(Pattern.compile("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(Pattern.compile("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");
+ // 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() {
+ s = new Scanner("test");
+ try {
+ s.findInLine((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ s.close();
+ try {
+ s.findInLine((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ s.findInLine("test");
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // exptected
+ }
+ }
+
+ /**
+ * @tests java.util.Scanner#skip(Pattern)
+ */
+ public void test_skip_LPattern() {
+ s = new Scanner("test");
+ try {
+ s.skip((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // 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
+ }
+ // Then, no matchResult will be thrown out.
+ try {
+ s.match();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s.skip(Pattern.compile("\\p{Digit}"));
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1, matchResult.end());
+
+ s.skip(Pattern.compile("\\p{Digit}+"));
+ matchResult = s.match();
+ assertEquals(1, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ s.close();
+ try {
+ s.skip(Pattern.compile("test"));
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // 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
+ }
+ try {
+ s.match();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(4, matchResult.end());
+
+ s.close();
+ try {
+ s.skip((Pattern) null);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ char [] chars = new char[1024];
+ Arrays.fill(chars, 'a');
+ stringBuilder.append(chars);
+ stringBuilder.append('3');
+ s = new Scanner(stringBuilder.toString());
+ s.skip(Pattern.compile("\\p{Lower}+\\p{Digit}"));
+ 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');
+ stringBuilder = new StringBuilder();
+ stringBuilder.append(chars);
+ s = new Scanner(stringBuilder.toString());
+ s.skip(Pattern.compile(".*"));
+ 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();
+ assertEquals(102400, matchResult.start());
+ assertEquals(102400, matchResult.end());
+ }
+
+ /**
+ * @tests java.util.Scanner#skip(String)
+ */
+ public void test_skip_LString() {
+ s = new Scanner("test");
+ try {
+ s.skip((String) null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextDouble()
+ */
+ public void test_nextDouble() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(123.0, s.nextDouble());
+ assertEquals(456.0, s.nextDouble());
+ assertEquals(123.4, s.nextDouble());
+ assertEquals(0.123, s.nextDouble());
+ try {
+ s.nextDouble();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(123.4, s.nextDouble());
+ assertEquals(-456.7, s.nextDouble());
+ assertEquals(123456.789, s.nextDouble());
+ try {
+ s.nextDouble();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(1.234E12, s.nextDouble());
+ assertEquals(-4.567E14, s.nextDouble());
+ assertEquals(1.23456789E-5, s.nextDouble());
+
+ s = new Scanner("NaN Infinity -Infinity");
+ 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);
+ assertEquals(Double.POSITIVE_INFINITY, s.nextDouble());
+
+ 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.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(23456.0, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertEquals(23.456, s.nextDouble());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(23.456, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertEquals(23456.0, s.nextDouble());
+
+ s = new Scanner("23,456.7 23.456,7");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(23456.7, s.nextDouble());
+ s.useLocale(Locale.GERMANY);
+ assertEquals(23456.7, s.nextDouble());
+
+ s = new Scanner("-123.4");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(-123.4, s.nextDouble());
+ }
+
+ /**
+ * @throws IOException
+ * @tests java.util.Scanner#nextBigDecimal()
+ */
+ public void test_nextBigDecimal() throws IOException {
+ s = new Scanner("123 45\u0666. 123.4 .123 ");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("123"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("456"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("0.123"), s.nextBigDecimal());
+ try {
+ s.nextBigDecimal();
+ fail("Should throw NoSuchElementException");
+ } catch (NoSuchElementException e) {
+ // Expected
+ }
+
+ s = new Scanner("+123.4 -456.7 123,456.789 0.1\u06623,4");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("123.4"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("-456.7"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("123456.789"), s.nextBigDecimal());
+ try {
+ s.nextBigDecimal();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ // Scientific notation
+ s = new Scanner("+123.4E10 -456.7e+12 123,456.789E-10");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("1.234E12"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("-4.567E14"), s.nextBigDecimal());
+ assertEquals(new BigDecimal("1.23456789E-5"), s.nextBigDecimal());
+
+ s = new Scanner("NaN");
+ try {
+ s.nextBigDecimal();
+ fail("Should throw InputMismatchException");
+ } catch (InputMismatchException e) {
+ // Expected
+ }
+
+ /*
+ * Different locale can only recognize corresponding locale sensitive
+ * string. ',' is used in many locales as group separator.
+ */
+ s = new Scanner("23,456 23,456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+ s.useLocale(Locale.GERMANY);
+ assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+
+ s = new Scanner("23.456 23.456");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("23.456"), s.nextBigDecimal());
+ s.useLocale(Locale.GERMANY);
+ assertEquals(new BigDecimal("23456"), s.nextBigDecimal());
+
+ s = new Scanner("23,456.7");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("23456.7"), s.nextBigDecimal());
+
+ s = new Scanner("-123.4");
+ s.useLocale(Locale.ENGLISH);
+ assertEquals(new BigDecimal("-123.4"), s.nextBigDecimal());
+ }
+
+ /**
+ * @tests java.util.Scanner#toString()
+ */
+ public void test_toString() {
+ s = new Scanner("test");
+ assertNotNull(s.toString());
+ }
+
+ /**
+ * @tests java.util.Scanner#nextLine()
+ */
+ public void test_nextLine() {
+ s = new Scanner("");
+ s.close();
+ try {
+ s.nextLine();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("test\r\ntest");
+ String result = s.nextLine();
+ assertEquals("test", result);
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(6, matchResult.end());
+
+ s = new Scanner("\u0085");
+ result = s.nextLine();
+ assertEquals("", result);
+ 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
+ }
+ try {
+ s.match();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("Ttest");
+ result = s.nextLine();
+ assertEquals("Ttest", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(5, matchResult.end());
+
+ s = new Scanner("\r\n");
+ result = s.nextLine();
+ assertEquals("", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(2, matchResult.end());
+
+ char[] chars = new char[1024];
+ Arrays.fill(chars, 'a');
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append(chars);
+ chars = new char[] { '+', '-' };
+ stringBuilder.append(chars);
+ stringBuilder.append("\u2028");
+ s = new Scanner(stringBuilder.toString());
+ result = s.nextLine();
+
+ assertEquals(stringBuilder.toString().substring(0, 1026), result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1027, matchResult.end());
+
+ chars = new char[1023];
+ Arrays.fill(chars, 'a');
+ stringBuilder = new StringBuilder();
+ stringBuilder.append(chars);
+ stringBuilder.append("\r\n");
+ s = new Scanner(stringBuilder.toString());
+ result = s.nextLine();
+
+ assertEquals(stringBuilder.toString().substring(0, 1023), result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1025, matchResult.end());
+
+ s = new Scanner(" ");
+ result = s.nextLine();
+ assertEquals(" ", result);
+
+ s = new Scanner("test\n\n\n");
+ result = s.nextLine();
+ assertEquals("test", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(5, matchResult.end());
+ result = s.nextLine();
+ matchResult = s.match();
+ assertEquals(5, matchResult.start());
+ assertEquals(6, matchResult.end());
+
+ s = new Scanner("\n\n\n");
+ result = s.nextLine();
+ assertEquals("", result);
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1, matchResult.end());
+ result = s.nextLine();
+ 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);
+
+ // Regression test for Harmony-4774
+ class CountReadable implements Readable {
+ int counter = 0;
+ public int read(CharBuffer charBuffer) throws IOException {
+ counter++;
+ charBuffer.append("hello\n");
+ return 6;
+ }
+ }
+ CountReadable cr = new CountReadable();
+ s = new Scanner(cr);
+ result = s.nextLine();
+ // 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);
+ }
+
+ /**
+ * @tests java.util.Scanner#hasNextLine()
+ */
+ public void test_hasNextLine() {
+ s = new Scanner("");
+ s.close();
+ try {
+ s.hasNextLine();
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+
+ s = new Scanner("test\r\ntest");
+ boolean result = s.hasNextLine();
+ assertTrue(result);
+ MatchResult matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(6, matchResult.end());
+
+ s = new Scanner("\u0085");
+ result = s.hasNextLine();
+ assertTrue(result);
+ 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();
+ assertEquals(0, matchResult.start());
+ assertEquals(5, matchResult.end());
+
+ char[] chars = new char[2048];
+ Arrays.fill(chars, 'a');
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append(chars);
+ s = new Scanner(stringBuilder.toString());
+ result = s.hasNextLine();
+ assertTrue(result);
+
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(2048, matchResult.end());
+
+ s = new Scanner("\n\n\n");
+ assertTrue(s.hasNextLine());
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1, matchResult.end());
+
+ // The scanner will not advance any input.
+ assertTrue(s.hasNextLine());
+ matchResult = s.match();
+ assertEquals(0, matchResult.start());
+ assertEquals(1, matchResult.end());
+ }
+
+ public void test_hasNextLine_sequence() throws IOException {
+ final PipedInputStream pis = new PipedInputStream();
+ final PipedOutputStream pos = new PipedOutputStream();
+ final Scanner scanner = new Scanner(pis);
+ pis.connect(pos);
+ final List<String> result = new ArrayList<String>();
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ while (scanner.hasNextLine()) {
+ result.add(scanner.nextLine());
+ }
+ }
+ });
+ thread.start();
+ for (int index = 0; index < 5; index++) {
+ pos.write(("line" + index + "\n").getBytes());
+ pos.flush();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ // Ignored
+ }
+ assertEquals(index + 1, result.size());
+ }
+ pis.close();
+ pos.close();
+ try {
+ thread.join(1000);
+ } catch (InterruptedException e) {
+ // Ignored
+ }
+ assertFalse(scanner.hasNextLine());
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ server = new ServerSocket(0);
+ address = new InetSocketAddress("127.0.0.1", server.getLocalPort());
+
+ client = SocketChannel.open();
+ client.connect(address);
+ serverSocket = server.accept();
+
+ os = serverSocket.getOutputStream();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ try {
+ serverSocket.close();
+ } catch (Exception e) {
+
+ }
+ try {
+ client.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ try {
+ server.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java
new file mode 100644
index 0000000..d8f4cc4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/luni/tests/java/util/UUIDTest.java
@@ -0,0 +1,457 @@
+/*
+ * 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.luni.tests.java.util;
+
+import java.util.UUID;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+import junit.framework.TestCase;
+
+public class UUIDTest extends TestCase {
+
+ /**
+ * @see UUID#UUID(long, long)
+ */
+ public void test_ConstructorJJ() {
+ UUID uuid = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+ assertEquals(2, uuid.variant());
+ assertEquals(1, uuid.version());
+ assertEquals(0x1d07decf81d4faeL, uuid.timestamp());
+ assertEquals(130742845922168750L, uuid.timestamp());
+ assertEquals(0x2765, uuid.clockSequence());
+ assertEquals(0xA0C91E6BF6L, uuid.node());
+ }
+
+ /**
+ * @see UUID#getLeastSignificantBits()
+ */
+ public void test_getLeastSignificantBits() {
+ UUID uuid = new UUID(0, 0);
+ assertEquals(0, uuid.getLeastSignificantBits());
+ uuid = new UUID(0, Long.MIN_VALUE);
+ assertEquals(Long.MIN_VALUE, uuid.getLeastSignificantBits());
+ uuid = new UUID(0, Long.MAX_VALUE);
+ assertEquals(Long.MAX_VALUE, uuid.getLeastSignificantBits());
+ }
+
+ /**
+ * @see UUID#getMostSignificantBits()
+ */
+ public void test_getMostSignificantBits() {
+ UUID uuid = new UUID(0, 0);
+ assertEquals(0, uuid.getMostSignificantBits());
+ uuid = new UUID(Long.MIN_VALUE, 0);
+ assertEquals(Long.MIN_VALUE, uuid.getMostSignificantBits());
+ uuid = new UUID(Long.MAX_VALUE, 0);
+ assertEquals(Long.MAX_VALUE, uuid.getMostSignificantBits());
+ }
+
+ /**
+ * @see UUID#version()
+ */
+ public void test_version() {
+ UUID uuid = new UUID(0, 0);
+ assertEquals(0, uuid.version());
+ uuid = new UUID(0x0000000000001000L, 0);
+ assertEquals(1, uuid.version());
+ uuid = new UUID(0x0000000000002000L, 0);
+ assertEquals(2, uuid.version());
+ uuid = new UUID(0x0000000000003000L, 0);
+ assertEquals(3, uuid.version());
+ uuid = new UUID(0x0000000000004000L, 0);
+ assertEquals(4, uuid.version());
+ uuid = new UUID(0x0000000000005000L, 0);
+ assertEquals(5, uuid.version());
+ }
+
+ /**
+ * @see UUID#variant()
+ */
+ public void test_variant() {
+ UUID uuid = new UUID(0, 0x0000000000000000L);
+ assertEquals(0, uuid.variant());
+ uuid = new UUID(0, 0x7000000000000000L);
+ assertEquals(0, uuid.variant());
+ uuid = new UUID(0, 0x3000000000000000L);
+ assertEquals(0, uuid.variant());
+ uuid = new UUID(0, 0x1000000000000000L);
+ assertEquals(0, uuid.variant());
+
+ uuid = new UUID(0, 0x8000000000000000L);
+ assertEquals(2, uuid.variant());
+ uuid = new UUID(0, 0xB000000000000000L);
+ assertEquals(2, uuid.variant());
+ uuid = new UUID(0, 0xA000000000000000L);
+ assertEquals(2, uuid.variant());
+ uuid = new UUID(0, 0x9000000000000000L);
+ assertEquals(2, uuid.variant());
+
+ uuid = new UUID(0, 0xC000000000000000L);
+ assertEquals(6, uuid.variant());
+ uuid = new UUID(0, 0xD000000000000000L);
+ assertEquals(6, uuid.variant());
+
+ uuid = new UUID(0, 0xE000000000000000L);
+ assertEquals(7, uuid.variant());
+ uuid = new UUID(0, 0xF000000000000000L);
+ assertEquals(7, uuid.variant());
+ }
+
+ /**
+ * @see UUID#timestamp()
+ */
+ public void test_timestamp() {
+ UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+ assertEquals(0x0, uuid.timestamp());
+
+ uuid = new UUID(0x7777777755551333L, 0x8000000000000000L);
+ assertEquals(0x333555577777777L, uuid.timestamp());
+
+ uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+ try {
+ uuid.timestamp();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+
+ uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+ try {
+ uuid.timestamp();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+ }
+
+ /**
+ * @see UUID#clockSequence()
+ */
+ public void test_clockSequence() {
+ UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+ assertEquals(0x0, uuid.clockSequence());
+
+ uuid = new UUID(0x0000000000001000L, 0x8FFF000000000000L);
+ assertEquals(0x0FFF, uuid.clockSequence());
+
+ uuid = new UUID(0x0000000000001000L, 0xBFFF000000000000L);
+ assertEquals(0x3FFF, uuid.clockSequence());
+
+ uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+ try {
+ uuid.clockSequence();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+
+ uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+ try {
+ uuid.clockSequence();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+ }
+
+ /**
+ * @see UUID#node()
+ */
+ public void test_node() {
+ UUID uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+ assertEquals(0x0, uuid.node());
+
+ uuid = new UUID(0x0000000000001000L, 0x8000FFFFFFFFFFFFL);
+ assertEquals(0xFFFFFFFFFFFFL, uuid.node());
+
+ uuid = new UUID(0x0000000000000000L, 0x8000000000000000L);
+ try {
+ uuid.node();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+
+ uuid = new UUID(0x0000000000002000L, 0x8000000000000000L);
+ try {
+ uuid.node();
+ fail("No UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {}
+ }
+
+ /**
+ * @see UUID#compareTo(UUID)
+ */
+ public void test_compareTo() {
+ UUID uuid1 = new UUID(0, 0);
+ assertEquals(0, uuid1.compareTo(uuid1));
+ UUID uuid2 = new UUID(1, 0);
+ assertEquals(-1, uuid1.compareTo(uuid2));
+ assertEquals(1, uuid2.compareTo(uuid1));
+
+ uuid2 = new UUID(0, 1);
+ assertEquals(-1, uuid1.compareTo(uuid2));
+ assertEquals(1, uuid2.compareTo(uuid1));
+ }
+
+ /**
+ * @see UUID#hashCode()
+ */
+ public void test_hashCode() {
+ UUID uuid = new UUID(0, 0);
+ assertEquals(0, uuid.hashCode());
+ uuid = new UUID(123, 123);
+ UUID uuidClone = new UUID(123, 123);
+ assertEquals(uuid.hashCode(), uuidClone.hashCode());
+ }
+
+ /**
+ * @see UUID#equals(Object)
+ */
+ public void test_equalsObject() {
+ UUID uuid1 = new UUID(0, 0);
+ assertEquals(uuid1, uuid1);
+ assertFalse(uuid1.equals(null));
+ assertFalse(uuid1.equals("NOT A UUID"));
+ UUID uuid2 = new UUID(0, 0);
+ assertEquals(uuid1, uuid2);
+ assertEquals(uuid2, uuid1);
+
+ uuid1 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+ uuid2 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+ assertEquals(uuid1, uuid2);
+ assertEquals(uuid2, uuid1);
+
+ uuid2 = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf7L);
+ assertFalse(uuid1.equals(uuid2));
+ assertFalse(uuid2.equals(uuid1));
+ }
+
+ /**
+ * @see UUID#toString()
+ */
+ public void test_toString() {
+ UUID uuid = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+ String actual = uuid.toString();
+ assertEquals("f81d4fae-7dec-11d0-a765-00a0c91e6bf6", actual);
+
+ uuid = new UUID(0x0000000000001000L, 0x8000000000000000L);
+ actual = uuid.toString();
+ assertEquals("00000000-0000-1000-8000-000000000000", actual);
+ }
+
+ /**
+ * @tests serialization/deserialization.
+ */
+ public void testSerializationSelf() throws Exception {
+ SerializationTest.verifySelf(new UUID(0xf81d4fae7dec11d0L,
+ 0xa76500a0c91e6bf6L));
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ SerializationTest.verifyGolden(this, new UUID(0xf81d4fae7dec11d0L,
+ 0xa76500a0c91e6bf6L));
+ }
+
+ /**
+ * @see UUID#randomUUID()
+ */
+ public void test_randomUUID() {
+ UUID uuid = UUID.randomUUID();
+ assertEquals(2, uuid.variant());
+ assertEquals(4, uuid.version());
+ }
+
+ /**
+ * @see UUID#nameUUIDFromBytes(byte[])
+ */
+ public void test_nameUUIDFromBytes() throws Exception {
+ byte[] name = { (byte) 0x6b, (byte) 0xa7, (byte) 0xb8, (byte) 0x11,
+ (byte) 0x9d, (byte) 0xad, (byte) 0x11, (byte) 0xd1,
+ (byte) 0x80, (byte) 0xb4, (byte) 0x00, (byte) 0xc0,
+ (byte) 0x4f, (byte) 0xd4, (byte) 0x30, (byte) 0xc8 };
+
+ UUID uuid = UUID.nameUUIDFromBytes(name);
+
+ assertEquals(2, uuid.variant());
+ assertEquals(3, uuid.version());
+
+ assertEquals(0xaff565bc2f771745L, uuid.getLeastSignificantBits());
+ assertEquals(0x14cdb9b4de013faaL, uuid.getMostSignificantBits());
+
+ uuid = UUID.nameUUIDFromBytes(new byte[0]);
+ assertEquals(2, uuid.variant());
+ assertEquals(3, uuid.version());
+
+ assertEquals(0xa9800998ecf8427eL, uuid.getLeastSignificantBits());
+ assertEquals(0xd41d8cd98f003204L, uuid.getMostSignificantBits());
+
+ try {
+ UUID.nameUUIDFromBytes(null);
+ fail("No NPE");
+ } catch (NullPointerException e) {}
+ }
+
+ /**
+ * @see UUID#fromString(String)
+ */
+ public void test_fromString() {
+ UUID actual = UUID.fromString("f81d4fae-7dec-11d0-a765-00a0c91e6bf6");
+ UUID expected = new UUID(0xf81d4fae7dec11d0L, 0xa76500a0c91e6bf6L);
+ assertEquals(expected, actual);
+
+ assertEquals(2, actual.variant());
+ assertEquals(1, actual.version());
+ assertEquals(130742845922168750L, actual.timestamp());
+ assertEquals(10085, actual.clockSequence());
+ assertEquals(690568981494L, actual.node());
+
+ actual = UUID.fromString("00000000-0000-1000-8000-000000000000");
+ expected = new UUID(0x0000000000001000L, 0x8000000000000000L);
+ assertEquals(expected, actual);
+
+ assertEquals(2, actual.variant());
+ assertEquals(1, actual.version());
+ assertEquals(0L, actual.timestamp());
+ assertEquals(0, actual.clockSequence());
+ assertEquals(0L, actual.node());
+
+ try {
+ UUID.fromString(null);
+ fail("No NPE");
+ } catch (NullPointerException e) {}
+
+ try {
+ UUID.fromString("");
+ fail("No IAE");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ UUID.fromString("f81d4fae_7dec-11d0-a765-00a0c91e6bf6");
+ fail("No IAE");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ UUID.fromString("f81d4fae-7dec_11d0-a765-00a0c91e6bf6");
+ fail("No IAE");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ UUID.fromString("f81d4fae-7dec-11d0_a765-00a0c91e6bf6");
+ fail("No IAE");
+ } catch (IllegalArgumentException e) {}
+
+ try {
+ UUID.fromString("f81d4fae-7dec-11d0-a765_00a0c91e6bf6");
+ fail("No IAE");
+ } catch (IllegalArgumentException e) {}
+ }
+
+ /**
+ * @tests java.util.UUID#fromString(String)
+ */
+ public void test_fromString_LString_Exception() {
+
+ UUID uuid = UUID.fromString("0-0-0-0-0");
+
+ try {
+ uuid = UUID.fromString("0-0-0-0-");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("-0-0-0-0-0");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("-0-0-0-0");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("-0-0-0-");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("0--0-0-0");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("0-0-0-0-");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("-1-0-0-0-0");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ uuid = UUID.fromString("123456789-0-0-0-0");
+ assertEquals(0x2345678900000000L, uuid.getMostSignificantBits());
+ assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+ uuid = UUID.fromString("111123456789-0-0-0-0");
+ assertEquals(0x2345678900000000L, uuid.getMostSignificantBits());
+ assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+ uuid = UUID.fromString("7fffffffffffffff-0-0-0-0");
+ assertEquals(0xffffffff00000000L, uuid.getMostSignificantBits());
+ assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+ try {
+ uuid = UUID.fromString("8000000000000000-0-0-0-0");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // expected
+ }
+
+ uuid = UUID
+ .fromString("7fffffffffffffff-7fffffffffffffff-7fffffffffffffff-0-0");
+ assertEquals(0xffffffffffffffffL, uuid.getMostSignificantBits());
+ assertEquals(0x0L, uuid.getLeastSignificantBits());
+
+ uuid = UUID.fromString("0-0-0-7fffffffffffffff-7fffffffffffffff");
+ assertEquals(0x0L, uuid.getMostSignificantBits());
+ assertEquals(0xffffffffffffffffL, uuid.getLeastSignificantBits());
+
+ try {
+ uuid = UUID.fromString("0-0-0-8000000000000000-0");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // expected
+ }
+
+ try {
+ uuid = UUID.fromString("0-0-0-0-8000000000000000");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
new file mode 100644
index 0000000..eb48992
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/AbstractBufferTest.java
@@ -0,0 +1,306 @@
+/* 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.tests.java.nio;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests a java.nio.Buffer instance.
+ */
+public class AbstractBufferTest extends TestCase {
+
+ protected Buffer baseBuf;
+
+ protected void setUp() throws Exception{
+ super.setUp();
+ baseBuf = ByteBuffer.allocate(10);
+ }
+
+ protected void tearDown() throws Exception{
+ super.tearDown();
+ }
+
+ public void testCapacity() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ public void testClear() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.clear();
+ assertSame(ret, baseBuf);
+ assertEquals(baseBuf.position(), 0);
+ assertEquals(baseBuf.limit(), baseBuf.capacity());
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$S
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testFlip() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.flip();
+ assertSame(ret, baseBuf);
+ assertEquals(baseBuf.position(), 0);
+ assertEquals(baseBuf.limit(), oldPosition);
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testHasRemaining() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ assertEquals(baseBuf.hasRemaining(), baseBuf.position() < baseBuf.limit());
+ baseBuf.position(baseBuf.limit());
+ assertFalse(baseBuf.hasRemaining());
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testIsReadOnly() {
+ baseBuf.isReadOnly();
+ }
+
+ /*
+ * Class under test for int limit()
+ */
+ public void testLimit() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer limit(int)
+ */
+ public void testLimitint() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.limit(baseBuf.limit());
+ assertSame(ret, baseBuf);
+
+ baseBuf.mark();
+ baseBuf.limit(baseBuf.capacity());
+ assertEquals(baseBuf.limit(), baseBuf.capacity());
+ // position should not change
+ assertEquals(baseBuf.position(), oldPosition);
+ // mark should be valid
+ baseBuf.reset();
+
+ if (baseBuf.capacity() > 0) {
+ baseBuf.limit(baseBuf.capacity());
+ baseBuf.position(baseBuf.capacity());
+ baseBuf.mark();
+ baseBuf.limit(baseBuf.capacity() - 1);
+ // position should be the new limit
+ assertEquals(baseBuf.position(), baseBuf.limit());
+ // mark should be invalid
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ try {
+ baseBuf.limit(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ baseBuf.limit(baseBuf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testMark() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.mark();
+ assertSame(ret, baseBuf);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ /*
+ * Class under test for int position()
+ */
+ public void testPosition() {
+ assertTrue(0 <= baseBuf.position() && baseBuf.position() <= baseBuf.limit()
+ && baseBuf.limit() <= baseBuf.capacity());
+ }
+
+ /*
+ * Class under test for Buffer position(int)
+ */
+ public void testPositionint() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ try {
+ baseBuf.position(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ baseBuf.position(baseBuf.limit() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.position());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.position(0);
+ assertEquals(baseBuf.position(), 0);
+ baseBuf.position(baseBuf.limit());
+ assertEquals(baseBuf.position(), baseBuf.limit());
+
+ if (baseBuf.capacity() > 0) {
+ baseBuf.limit(baseBuf.capacity());
+ baseBuf.position(baseBuf.limit());
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit() - 1);
+ assertEquals(baseBuf.position(), baseBuf.limit() - 1);
+ // mark should be invalid
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ Buffer ret = baseBuf.position(0);
+ assertSame(ret, baseBuf);
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testRemaining() {
+ assertEquals(baseBuf.remaining(), baseBuf.limit() - baseBuf.position());
+ }
+
+ public void testReset() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ baseBuf.mark();
+ baseBuf.position(baseBuf.limit());
+ baseBuf.reset();
+ assertEquals(baseBuf.position(), oldPosition);
+
+ Buffer ret = baseBuf.reset();
+ assertSame(ret, baseBuf);
+
+ baseBuf.clear();
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+
+ public void testRewind() {
+ // save state
+ int oldPosition = baseBuf.position();
+ int oldLimit = baseBuf.limit();
+
+ Buffer ret = baseBuf.rewind();
+ assertEquals(baseBuf.position(), 0);
+ assertSame(ret, baseBuf);
+ try {
+ baseBuf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // restore state
+ baseBuf.limit(oldLimit);
+ baseBuf.position(oldPosition);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
new file mode 100644
index 0000000..39059fe
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferOverflowExceptionTest.java
@@ -0,0 +1,52 @@
+/* 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class BufferOverflowExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new BufferOverflowException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new BufferOverflowException());
+ }
+
+ /**
+ *@tests {@link java.nio.BufferOverflowException#BufferOverflowException()}
+ */
+ public void test_Constructor() {
+ BufferOverflowException exception = new BufferOverflowException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getLocalizedMessage());
+ assertNull(exception.getCause());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
new file mode 100644
index 0000000..a056ebf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/BufferUnderflowExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio;
+
+import java.nio.BufferUnderflowException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for BufferUnderflowException
+ */
+public class BufferUnderflowExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new BufferUnderflowException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new BufferUnderflowException());
+ }
+
+ /**
+ *@tests {@link java.nio.BufferUnderflowException#BufferUnderflowException()}
+ */
+ public void test_Constructor() {
+ BufferUnderflowException exception = new BufferUnderflowException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getLocalizedMessage());
+ assertNull(exception.getCause());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
new file mode 100644
index 0000000..d6d8681
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteBufferTest.java
@@ -0,0 +1,2177 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+import java.util.Arrays;
+
+/**
+ * Tests java.nio.ByteBuffer
+ *
+ */
+public class ByteBufferTest extends AbstractBufferTest {
+ protected static final int SMALL_TEST_LENGTH = 5;
+ protected static final int BUFFER_LENGTH = 250;
+
+ protected ByteBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = ByteBuffer.allocate(10);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testArray() {
+ if (buf.hasArray()) {
+ byte array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testArrayOffset() {
+ if (buf.hasArray()) {
+ byte array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ ByteBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.position(1);
+ buf.limit(SMALL_TEST_LENGTH);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (byte) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ if (!buf.isReadOnly()) {
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.clear();
+ ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+ loadTestData1(buf);
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(SMALL_TEST_LENGTH);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ assertTrue(ByteBuffer.wrap(new byte[21]).compareTo(ByteBuffer.allocateDirect(21)) == 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ ByteBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ ByteBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for byte get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer get(byte[])
+ */
+ public void testGetbyteArray() {
+ byte array[] = new byte[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ByteBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.get((byte[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer get(byte[], int, int)
+ */
+ public void testGetbyteArrayintint() {
+ buf.clear();
+ byte array[] = new byte[buf.capacity()];
+
+ try {
+ buf.get(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((byte[])null, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ ByteBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for byte get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ if (buf.hasArray()) {
+ assertNotNull(buf.array());
+ } else {
+ if (buf.isReadOnly()) {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ // Note:can not tell when to throw
+ // UnsupportedOperationException
+ // or ReadOnlyBufferException, so catch all.
+ }
+ } else {
+ try {
+ buf.array();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+ }
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ loadTestData1(buf);
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ ByteBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ duplicate.position(buf.capacity()/2);
+ assertTrue(buf.hashCode()!= duplicate.hashCode());
+ }
+
+ //for the testHashCode() method of readonly subclasses
+ protected void readOnlyHashCode() {
+ //create a new buffer initiated with some data
+ ByteBuffer buf = ByteBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ buf.clear();
+ ByteBuffer readonly = buf.asReadOnlyBuffer();
+ ByteBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(),readonly.hashCode());
+ duplicate.position(buf.capacity()/2);
+ assertTrue(buf.hashCode()!= duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ buf.isDirect();
+ }
+
+ public void testOrder() {
+ // BIG_ENDIAN is the default byte order
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+
+ // Regression test for HARMONY-798
+ buf.order((ByteOrder)null);
+ assertEquals(ByteOrder.LITTLE_ENDIAN, buf.order());
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte)
+ */
+ public void testPutbyte() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.put((byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ByteBuffer ret = buf.put((byte) i);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte[])
+ */
+ public void testPutbyteArray() {
+ byte array[] = new byte[1];
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (byte) i;
+ ByteBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((byte[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(byte[], int, int)
+ */
+ public void testPutbyteArrayintint() {
+ buf.clear();
+ byte array[] = new byte[buf.capacity()];
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ try {
+ buf.put(new byte[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ buf.put(array, 2, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((byte[])null, 2, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ ByteBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(java.nio.ByteBuffer)
+ */
+ public void testPutByteBuffer() {
+ ByteBuffer other = ByteBuffer.allocate(buf.capacity());
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.put(other);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.clear();
+ buf.put((ByteBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(ByteBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ try {
+ buf.put((ByteBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ ByteBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ByteBuffer put(int, byte)
+ */
+ public void testPutintbyte() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.put(0, (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ ByteBuffer ret = buf.put(i, (byte) i);
+ assertEquals(buf.get(i), (byte) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (byte) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ ByteBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (byte) 0, slice.capacity());
+ buf.put(2, (byte) 100);
+ assertEquals(slice.get(1), 100);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Byte") >= 0 || str.indexOf("byte") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ public void testAsCharBuffer() {
+ CharBuffer charBuffer;
+ byte bytes[] = new byte[2];
+ char value;
+
+ // test BIG_ENDIAN char buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = charBuffer.get();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN char buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = charBuffer.get();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN char buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ value = (char) charBuffer.remaining();
+ charBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN char buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ charBuffer = buf.asCharBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, charBuffer.order());
+ while (charBuffer.remaining() > 0) {
+ value = (char) charBuffer.remaining();
+ charBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, char2bytes(value, buf.order())));
+ }
+ }
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsDoubleBuffer() {
+ DoubleBuffer doubleBuffer;
+ byte bytes[] = new byte[8];
+ double value;
+
+ // test BIG_ENDIAN double buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = doubleBuffer.get();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ // test LITTLE_ENDIAN double buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = doubleBuffer.get();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN double buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ value = (double) doubleBuffer.remaining();
+ doubleBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN double buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ doubleBuffer = buf.asDoubleBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, doubleBuffer.order());
+ while (doubleBuffer.remaining() > 0) {
+ value = (double) doubleBuffer.remaining();
+ doubleBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, double2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsFloatBuffer() {
+ FloatBuffer floatBuffer;
+ byte bytes[] = new byte[4];
+ float value;
+
+ // test BIG_ENDIAN float buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = floatBuffer.get();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ // test LITTLE_ENDIAN float buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = floatBuffer.get();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN float buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ value = (float) floatBuffer.remaining();
+ floatBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN float buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ floatBuffer = buf.asFloatBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, floatBuffer.order());
+ while (floatBuffer.remaining() > 0) {
+ value = (float) floatBuffer.remaining();
+ floatBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, float2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsIntBuffer() {
+ IntBuffer intBuffer;
+ byte bytes[] = new byte[4];
+ int value;
+
+ // test BIG_ENDIAN int buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = intBuffer.get();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN int buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = intBuffer.get();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN int buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ value = (int) intBuffer.remaining();
+ intBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN int buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ intBuffer = buf.asIntBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, intBuffer.order());
+ while (intBuffer.remaining() > 0) {
+ value = (int) intBuffer.remaining();
+ intBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, int2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsLongBuffer() {
+ LongBuffer longBuffer;
+ byte bytes[] = new byte[8];
+ long value;
+
+ // test BIG_ENDIAN long buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = longBuffer.get();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN long buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = longBuffer.get();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN long buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ value = (long) longBuffer.remaining();
+ longBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN long buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ longBuffer = buf.asLongBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, longBuffer.order());
+ while (longBuffer.remaining() > 0) {
+ value = (long) longBuffer.remaining();
+ longBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, long2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testAsShortBuffer() {
+ ShortBuffer shortBuffer;
+ byte bytes[] = new byte[2];
+ short value;
+
+ // test BIG_ENDIAN short buffer, read
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = shortBuffer.get();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ // test LITTLE_ENDIAN short buffer, read
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ buf.get(bytes);
+ value = shortBuffer.get();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ if (!buf.isReadOnly()) {
+ // test BIG_ENDIAN short buffer, write
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.BIG_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ value = (short) shortBuffer.remaining();
+ shortBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+ }
+
+ // test LITTLE_ENDIAN short buffer, write
+ buf.clear();
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ shortBuffer = buf.asShortBuffer();
+ assertSame(ByteOrder.LITTLE_ENDIAN, shortBuffer.order());
+ while (shortBuffer.remaining() > 0) {
+ value = (short) shortBuffer.remaining();
+ shortBuffer.put(value);
+ buf.get(bytes);
+ assertTrue(Arrays.equals(bytes, short2bytes(value, buf.order())));
+ }
+ }
+
+ buf.clear();
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetChar() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getChar();
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getChar();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetCharint() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getChar(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2char(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getChar(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getChar(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutChar() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putChar((char) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (char) i;
+ buf.mark();
+ buf.putChar(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putChar(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutCharint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putChar(0, (char) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ char value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (char) i;
+ buf.position(i);
+ buf.putChar(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(char2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putChar(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putChar(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ try {
+ ByteBuffer.allocateDirect(16).putChar(Integer.MAX_VALUE, 'h');
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testGetDouble() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getDouble();
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getDouble();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetDoubleint() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getDouble(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ if (!(Double.isNaN(bytes2double(bytes, buf.order())) && Double
+ .isNaN(value))) {
+ assertEquals(bytes2double(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getDouble(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getDouble(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+
+ try {
+ ByteBuffer.allocateDirect(16).getDouble(Integer.MAX_VALUE);
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testPutDouble() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putDouble((double) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (double) i;
+ buf.mark();
+ buf.putDouble(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putDouble(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutDoubleint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putDouble(0, (double) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ double value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (double) i;
+ buf.position(i);
+ buf.putDouble(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(double2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putDouble(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putDouble(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetFloat() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getFloat();
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getFloat();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetFloatint() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getFloat(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ if (!(Float.isNaN(bytes2float(bytes, buf.order())) && Float
+ .isNaN(value))) {
+ assertEquals(bytes2float(bytes, buf.order()), value, 0.00);
+ }
+ }
+
+ try {
+ buf.getFloat(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getFloat(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutFloat() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putFloat((float) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (float) i;
+ buf.mark();
+ buf.putFloat(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putFloat(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutFloatint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putFloat(0, (float) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ float value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (float) i;
+ buf.position(i);
+ buf.putFloat(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(float2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putFloat(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putFloat(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetInt() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getInt();
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getInt();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetIntint() {
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getInt(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2int(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getInt(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getInt(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ try {
+ ByteBuffer.allocateDirect(16).getInt(Integer.MAX_VALUE);
+ } catch (IndexOutOfBoundsException e) {
+ //expected
+ }
+ }
+
+ public void testPutInt() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putInt((int) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (int) i;
+ buf.mark();
+ buf.putInt(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putInt(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutIntint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putInt(0, (int) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 4;
+ byte bytes[] = new byte[nbytes];
+ int value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (int) i;
+ buf.position(i);
+ buf.putInt(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(int2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putInt(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putInt(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetLong() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getLong();
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getLong();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetLongint() {
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getLong(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2long(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getLong(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getLong(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutLong() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putLong((long) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (long) i;
+ buf.mark();
+ buf.putLong(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putLong(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutLongint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putLong(0, (long) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 8;
+ byte bytes[] = new byte[nbytes];
+ long value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (long) i;
+ buf.position(i);
+ buf.putLong(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(long2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putLong(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putLong(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetShort() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ assertEquals(i * nbytes, buf.position());
+ buf.mark();
+ buf.get(bytes);
+ buf.reset();
+ value = buf.getShort();
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getShort();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testGetShortint() {
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ buf.position(i);
+ value = buf.getShort(i);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertEquals(bytes2short(bytes, buf.order()), value);
+ }
+
+ try {
+ buf.getShort(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.getShort(buf.limit() - nbytes + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutShort() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.clear();
+ buf.putShort((short) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value = 0;
+ buf.clear();
+ for (int i = 0; buf.remaining() >= nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (short) i;
+ buf.mark();
+ buf.putShort(value);
+ assertEquals((i + 1) * nbytes, buf.position());
+ buf.reset();
+ buf.get(bytes);
+ assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putShort(value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ public void testPutShortint() {
+ if (buf.isReadOnly()) {
+ try {
+ buf.putShort(0, (short) 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ return;
+ }
+
+ int nbytes = 2;
+ byte bytes[] = new byte[nbytes];
+ short value = 0;
+ buf.clear();
+ for (int i = 0; i <= buf.limit() - nbytes; i++) {
+ buf.order(i % 2 == 0 ? ByteOrder.BIG_ENDIAN
+ : ByteOrder.LITTLE_ENDIAN);
+ value = (short) i;
+ buf.position(i);
+ buf.putShort(i, value);
+ assertEquals(i, buf.position());
+ buf.get(bytes);
+ assertTrue(Arrays.equals(short2bytes(value, buf.order()), bytes));
+ }
+
+ try {
+ buf.putShort(-1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.putShort(buf.limit() - nbytes + 1, value);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ buf.order(ByteOrder.BIG_ENDIAN);
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer.wrap(byte[],int,int)
+ */
+ public void testWrappedByteBuffer_null_array() {
+ // Regression for HARMONY-264
+ byte array[] = null;
+ try {
+ ByteBuffer.wrap(array, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+ try {
+ ByteBuffer.wrap(new byte[10], Integer.MAX_VALUE, 2);
+ fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ }
+ }
+
+ private void loadTestData1(byte array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (byte) i;
+ }
+ }
+
+ private void loadTestData2(byte array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (byte) (length - i);
+ }
+ }
+
+ private void loadTestData1(ByteBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (byte) i);
+ }
+ }
+
+ private void loadTestData2(ByteBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (byte) (buf.capacity() - i));
+ }
+ }
+
+ private void assertContentEquals(ByteBuffer buf, byte array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ private void assertContentEquals(ByteBuffer buf, ByteBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ private void assertContentLikeTestData1(ByteBuffer buf,
+ int startIndex, byte startValue, int length) {
+ byte value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (byte) (value + 1);
+ }
+ }
+
+ private int bytes2int(byte bytes[], ByteOrder order) {
+ int nbytes = 4, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ int result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = result << 8;
+ result = result | (bytes[p] & 0xff);
+ p += step;
+ }
+ return result;
+ }
+
+ private long bytes2long(byte bytes[], ByteOrder order) {
+ int nbytes = 8, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ long result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = result << 8;
+ result = result | (bytes[p] & 0xff);
+ p += step;
+ }
+ return result;
+ }
+
+ private short bytes2short(byte bytes[], ByteOrder order) {
+ int nbytes = 2, bigHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ bigHead = 0;
+ step = 1;
+ } else {
+ bigHead = nbytes - 1;
+ step = -1;
+ }
+ short result = 0;
+ int p = bigHead;
+ for (int i = 0; i < nbytes; i++) {
+ result = (short) (result << 8);
+ result = (short) (result | (bytes[p] & 0xff));
+ p += step;
+ }
+ return result;
+ }
+
+ private char bytes2char(byte bytes[], ByteOrder order) {
+ return (char) bytes2short(bytes, order);
+ }
+
+ private float bytes2float(byte bytes[], ByteOrder order) {
+ return Float.intBitsToFloat(bytes2int(bytes, order));
+ }
+
+ private double bytes2double(byte bytes[], ByteOrder order) {
+ return Double.longBitsToDouble(bytes2long(bytes, order));
+ }
+
+ private byte[] int2bytes(int value, ByteOrder order) {
+ int nbytes = 4, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = value >> 8;
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] long2bytes(long value, ByteOrder order) {
+ int nbytes = 8, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = value >> 8;
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] short2bytes(short value, ByteOrder order) {
+ int nbytes = 2, smallHead, step;
+ if (order == ByteOrder.BIG_ENDIAN) {
+ smallHead = nbytes - 1;
+ step = -1;
+ } else {
+ smallHead = 0;
+ step = 1;
+ }
+ byte bytes[] = new byte[nbytes];
+ int p = smallHead;
+ for (int i = 0; i < nbytes; i++) {
+ bytes[p] = (byte) (value & 0xff);
+ value = (short) (value >> 8);
+ p += step;
+ }
+ return bytes;
+ }
+
+ private byte[] char2bytes(char value, ByteOrder order) {
+ return short2bytes((short) value, order);
+ }
+
+ private byte[] float2bytes(float value, ByteOrder order) {
+ return int2bytes(Float.floatToRawIntBits(value), order);
+ }
+
+ private byte[] double2bytes(double value, ByteOrder order) {
+ return long2bytes(Double.doubleToRawLongBits(value), order);
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
similarity index 60%
copy from luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
copy to harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
index 7fe2d7f..8f41904 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/EndOfBufferException.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ByteOrderTest.java
@@ -15,19 +15,26 @@
* limitations under the License.
*/
-package org.apache.harmony.xnet.provider.jsse;
+package org.apache.harmony.nio.tests.java.nio;
-import java.io.IOException;
+import java.nio.ByteOrder;
+
+import junit.framework.TestCase;
/**
- * This exception indicates that data could not be read from the stream because the underlying input
- * stream reached its end.
+ * Test java.nio.ByteOrder
+ *
*/
-public class EndOfBufferException extends IOException {
+public class ByteOrderTest extends TestCase {
- private static final long serialVersionUID = 1838636631255369519L;
+ public void testToString() {
+ assertEquals(ByteOrder.BIG_ENDIAN.toString(), "BIG_ENDIAN");
+ assertEquals(ByteOrder.LITTLE_ENDIAN.toString(), "LITTLE_ENDIAN");
+ }
- public EndOfBufferException() {
+ public void testNativeOrder() {
+ ByteOrder o = ByteOrder.nativeOrder();
+ assertTrue(o == ByteOrder.BIG_ENDIAN || o == ByteOrder.LITTLE_ENDIAN);
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
new file mode 100644
index 0000000..8a7c5f3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/CharBufferTest.java
@@ -0,0 +1,1081 @@
+/*
+ * 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.tests.java.nio;
+
+import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.CharBuffer;
+import java.nio.InvalidMarkException;
+import java.nio.ReadOnlyBufferException;
+
+/**
+ * Tests java.nio.CharBuffer
+ *
+ */
+public class CharBufferTest extends AbstractBufferTest {
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected CharBuffer buf;
+
+ private static char[] chars = "123456789a".toCharArray();
+
+ protected void setUp() throws Exception{
+ char[] charscopy = new char[chars.length];
+ System.arraycopy(chars, 0, charscopy, 0, chars.length);
+ buf = CharBuffer.wrap(charscopy);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception{
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testArray() {
+ char array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ char array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertEquals(buf.capacity(), readonly.capacity());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ int originalPosition = (buf.position() + buf.limit()) / 2;
+ buf.position(originalPosition);
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertEquals(buf.capacity(), readonly.capacity());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), originalPosition);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), originalPosition);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ CharBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (char) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ buf.clear();
+ CharBuffer other = CharBuffer.allocate(buf.capacity());
+ other.put(buf);
+ other.clear();
+ buf.clear();
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ assertTrue(buf.compareTo(other) == 0);
+ assertTrue(other.compareTo(buf) == 0);
+ other.limit(SMALL_TEST_LENGTH);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ // mark the position 0
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ CharBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertEquals(buf.capacity(), duplicate.capacity());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to
+ // buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // mark another position
+ buf.clear();
+ int originalPosition = (buf.position() + buf.limit()) / 2;
+ buf.position(originalPosition);
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertEquals(buf.capacity(), duplicate.capacity());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to
+ // buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), originalPosition);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), originalPosition);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ CharBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for char get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer get(char[])
+ */
+ public void testGetcharArray() {
+ char array[] = new char[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ CharBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer get(char[], int, int)
+ */
+ public void testGetcharArrayintint() {
+ buf.clear();
+ char array[] = new char[buf.capacity()];
+
+ try {
+ buf.get(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((char[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ CharBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for char get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ loadTestData1(buf);
+ CharBuffer readonly = buf.asReadOnlyBuffer();
+ CharBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+ assertTrue(buf.capacity() > SMALL_TEST_LENGTH);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char)
+ */
+ public void testPutchar() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ CharBuffer ret = buf.put((char) i);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char[])
+ */
+ public void testPutcharArray() {
+ char array[] = new char[1];
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (char) i;
+ CharBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(char[], int, int)
+ */
+ public void testPutcharArrayintint() {
+ buf.clear();
+ char array[] = new char[buf.capacity()];
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((char[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ CharBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(java.nio.CharBuffer)
+ */
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(buf.capacity());
+
+ try {
+ buf.put((CharBuffer) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(CharBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((CharBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ CharBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.CharBuffer put(int, char)
+ */
+ public void testPutintchar() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ CharBuffer ret = buf.put(i, (char) i);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ CharBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (char) 0, slice.capacity());
+ buf.put(2, (char) 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String expected = "";
+ for (int i = buf.position(); i < buf.limit(); i++) {
+ expected += buf.get(i);
+ }
+ String str = buf.toString();
+ assertEquals(expected, str);
+ }
+
+ public void testCharAt() {
+ for (int i = 0; i < buf.remaining(); i++) {
+ assertEquals(buf.get(buf.position() + i), buf.charAt(i));
+ }
+ try {
+ buf.charAt(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.charAt(buf.remaining());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testLength() {
+ assertEquals(buf.length(), buf.remaining());
+ }
+
+ public void testSubSequence() {
+ try {
+ buf.subSequence(-1, buf.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.subSequence(buf.length() + 1, buf.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.subSequence(buf.length(), buf.length()).length(), 0);
+ try {
+ buf.subSequence(1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.subSequence(1, buf.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ assertEquals(buf.subSequence(0, buf.length()).toString(), buf
+ .toString());
+
+ if (buf.length() >= 2) {
+ assertEquals(buf.subSequence(1, buf.length() - 1).toString(), buf
+ .toString().substring(1, buf.length() - 1));
+ }
+ }
+
+ public void testPutString() {
+ String str = " ";
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ str = "" + (char) i;
+ CharBuffer ret = buf.put(str);
+ assertEquals(buf.get(i), (char) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(str);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutStringintint() {
+ buf.clear();
+ String str = String.valueOf(new char[buf.capacity()]);
+
+ // Throw a BufferOverflowException and no character is transfered to
+ // CharBuffer
+ try {
+ buf.put(String.valueOf(new char[buf.capacity() + 1]), 0, buf
+ .capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertEquals(0, buf.position());
+
+ buf.clear();
+ try {
+ buf.put(str, -1, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(str, str.length() + 1, str.length() + 2);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.put(str, str.length(), str.length());
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(str, 2, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(str, 2, str.length() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ char array[] = new char[buf.capacity()];
+ loadTestData2(array, 0, array.length);
+ str = String.valueOf(array);
+
+ CharBuffer ret = buf.put(str, 0, str.length());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, str.toCharArray(), 0, str.length());
+ assertSame(ret, buf);
+ }
+
+ void loadTestData1(char array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (char) i;
+ }
+ }
+
+ void loadTestData2(char array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (char) (length - i);
+ }
+ }
+
+ void loadTestData1(CharBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (char) i);
+ }
+ }
+
+ void loadTestData2(CharBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (char) (buf.capacity() - i));
+ }
+ }
+
+ private void assertContentEquals(CharBuffer buf, char array[], int offset,
+ int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ private void assertContentEquals(CharBuffer buf, CharBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ private void assertContentLikeTestData1(CharBuffer buf, int startIndex,
+ char startValue, int length) {
+ char value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (char) (value + 1);
+ }
+ }
+
+ public void testAppendSelf() throws Exception {
+ CharBuffer cb = CharBuffer.allocate(10);
+ CharBuffer cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ assertEquals(cb2, cb);
+
+ cb.put("abc");
+ cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ cb2.clear();
+ assertEquals(cb2, cb);
+
+ cb.put("edfg");
+ cb.clear();
+ cb2 = cb.duplicate();
+ cb.append(cb);
+ assertEquals(10, cb.position());
+ cb.clear();
+ cb2.clear();
+ assertEquals(cb, cb2);
+ }
+
+ public void testAppendOverFlow() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(1);
+ CharSequence cs = "String";
+ cb.put('A');
+ try {
+ cb.append('C');
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs);
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs, 1, 2);
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ public void testReadOnlyMap() throws IOException {
+ CharBuffer cb = CharBuffer.wrap("ABCDE").asReadOnlyBuffer();
+ CharSequence cs = "String";
+ try {
+ cb.append('A');
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ try {
+ cb.append(cs, 1, 2);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ cb.append(cs, 1, 1);
+ }
+
+ public void testAppendCNormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(2);
+ cb.put('A');
+ assertSame(cb, cb.append('B'));
+ assertEquals('B', cb.get(1));
+ }
+
+ public void testAppendCharSequenceNormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.put('A');
+ assertSame(cb, cb.append("String"));
+ assertEquals("AString", cb.flip().toString());
+ cb.append(null);
+ assertEquals("null", cb.flip().toString());
+ }
+
+ public void testAppendCharSequenceIINormal() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.put('A');
+ assertSame(cb, cb.append("String", 1, 3));
+ assertEquals("Atr", cb.flip().toString());
+
+ cb.append(null, 0, 1);
+ assertEquals("n", cb.flip().toString());
+ }
+
+ public void testAppendCharSequenceII_IllegalArgument() throws IOException {
+ CharBuffer cb = CharBuffer.allocate(10);
+ cb.append("String", 0, 0);
+ cb.append("String", 2, 2);
+ try {
+ cb.append("String", -1, 1);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", -1, -1);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 2);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 0);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ try {
+ cb.append("String", 3, 110);
+ fail("should throw IndexOutOfBoundsException.");
+ } catch (IndexOutOfBoundsException ex) {
+ // expected;
+ }
+ }
+
+ public void testReadCharBuffer() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(10);
+ assertEquals(6, source.read(target));
+ assertEquals("String", target.flip().toString());
+ // return -1 when nothing to read
+ assertEquals(-1, source.read(target));
+ // NullPointerException
+ try {
+ assertEquals(-1, source.read(null));
+ fail("should throw NullPointerException.");
+ } catch (NullPointerException ex) {
+ // expected;
+ }
+
+ }
+
+ public void testReadReadOnly() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(10).asReadOnlyBuffer();
+ try {
+ source.read(target);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ // if target has no remaining, needn't to check the isReadOnly
+ target.flip();
+ assertEquals(0, source.read(target));
+ }
+
+ public void testReadOverflow() throws IOException {
+ CharBuffer source = CharBuffer.wrap("String");
+ CharBuffer target = CharBuffer.allocate(1);
+ assertEquals(1, source.read(target));
+ assertEquals("S", target.flip().toString());
+ assertEquals(1, source.position());
+ }
+
+ public void testReadSelf() throws Exception {
+ CharBuffer source = CharBuffer.wrap("abuffer");
+ try {
+ source.read(source);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ public void testRead_scenario1() throws Exception {
+ char[] charArray = new char[] { 'a', 'b' };
+ CharBuffer charBuffer = CharBuffer.wrap(charArray);
+ try {
+ charBuffer.read(charBuffer);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ charBuffer.put(charArray);
+ assertEquals(-1, charBuffer.read(charBuffer));
+ }
+
+ public void testRead_scenario2() throws Exception {
+ CharBuffer charBufferA = CharBuffer.allocate(0);
+ CharBuffer allocateBuffer = CharBuffer.allocate(1);
+ CharBuffer charBufferB = CharBuffer.wrap(allocateBuffer);
+ assertEquals(-1, charBufferA.read(charBufferB));
+
+ allocateBuffer.append(allocateBuffer);
+ charBufferB = CharBuffer.wrap(allocateBuffer);
+ assertEquals(-1, charBufferA.read(charBufferB));
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
new file mode 100644
index 0000000..f274676
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectByteBufferTest.java
@@ -0,0 +1,60 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class DirectByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocateDirect(int)
+ *
+ */
+ public void testAllocatedByteBuffer_IllegalArg() {
+ try {
+ ByteBuffer.allocateDirect(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ // Android direct byte buffers have backing arrays.
+ assertTrue(buf.hasArray());
+ // assertFalse(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
new file mode 100644
index 0000000..83cfc9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectCharBufferTest.java
@@ -0,0 +1,61 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectCharBufferTest extends CharBufferTest {
+
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asCharBuffer();
+ super.loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
new file mode 100644
index 0000000..561c0fa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectDoubleBufferTest.java
@@ -0,0 +1,60 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectDoubleBufferTest extends DoubleBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asDoubleBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
new file mode 100644
index 0000000..8739c1b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectFloatBufferTest.java
@@ -0,0 +1,61 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectFloatBufferTest extends FloatBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asFloatBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
new file mode 100644
index 0000000..393366e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectIntBufferTest.java
@@ -0,0 +1,61 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectIntBufferTest extends IntBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*4).asIntBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
new file mode 100644
index 0000000..245cd25
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectLongBufferTest.java
@@ -0,0 +1,62 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+
+public class DirectLongBufferTest extends LongBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*8).asLongBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
new file mode 100644
index 0000000..9ae290a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DirectShortBufferTest.java
@@ -0,0 +1,61 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+
+public class DirectShortBufferTest extends ShortBufferTest {
+ public void setUp(){
+ buf = ByteBuffer.allocateDirect(BUFFER_LENGTH*2).asShortBuffer();
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ public void tearDown(){
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertTrue(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.BIG_ENDIAN, buf.order());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
new file mode 100644
index 0000000..40ff2e0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DoubleBufferTest.java
@@ -0,0 +1,664 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.DoubleBuffer
+ */
+public class DoubleBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected DoubleBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ /*
+ * Test with bit sequences that represent the IEEE754 doubles Positive
+ * infinity, negative infinity, and NaN.
+ */
+ public void testNaNs() {
+ long[] nans = new long[] { 0x7ff0000000000000L, 0xfff0000000000000L,
+ 0x7ff8000000000000L };
+ for (int i = 0; i < nans.length; i++) {
+ long longBitsIn = nans[i];
+ double dbl = Double.longBitsToDouble(longBitsIn);
+ long longBitsOut = Double.doubleToRawLongBits(dbl);
+ // Sanity check
+ assertTrue(longBitsIn == longBitsOut);
+
+ // Store the double and retrieve it
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ buffer.putDouble(dbl);
+ double bufDoubleOut = buffer.getDouble(0);
+
+ // Check the bits sequence was not normalized
+ long bufLongOut = Double.doubleToRawLongBits(bufDoubleOut);
+ assertTrue(longBitsIn == bufLongOut);
+ }
+ }
+
+ public void testArray() {
+ double array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ double array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ DoubleBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1.0, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+
+ DoubleBuffer dbuffer1 = DoubleBuffer.wrap(new double[] { Double.NaN });
+ DoubleBuffer dbuffer2 = DoubleBuffer.wrap(new double[] { Double.NaN });
+ DoubleBuffer dbuffer3 = DoubleBuffer.wrap(new double[] { 42d });
+
+ assertEquals("Failed equal comparison with NaN entry", 0, dbuffer1
+ .compareTo(dbuffer2));
+ assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer3
+ .compareTo(dbuffer1));
+ assertEquals("Failed greater than comparison with NaN entry", 1, dbuffer1
+ .compareTo(dbuffer3));
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ DoubleBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ // FIXME
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ DoubleBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for double get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer get(double[])
+ */
+ public void testGetdoubleArray() {
+ double array[] = new double[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ DoubleBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer get(double[], int, int)
+ */
+ public void testGetdoubleArrayintint() {
+ buf.clear();
+ double array[] = new double[buf.capacity()];
+
+ try {
+ buf.get(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((double[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ DoubleBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for double get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ DoubleBuffer readonly = buf.asReadOnlyBuffer();
+ DoubleBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double)
+ */
+ public void testPutdouble() {
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ DoubleBuffer ret = buf.put((double) i);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double[])
+ */
+ public void testPutdoubleArray() {
+ double array[] = new double[1];
+
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (double) i;
+ DoubleBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(double[], int, int)
+ */
+ public void testPutdoubleArrayintint() {
+ buf.clear();
+ double array[] = new double[buf.capacity()];
+
+ try {
+ buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((double[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ DoubleBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(java.nio.DoubleBuffer)
+ */
+ public void testPutDoubleBuffer() {
+ DoubleBuffer other = DoubleBuffer.allocate(buf.capacity());
+
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(DoubleBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ DoubleBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.DoubleBuffer put(int, double)
+ */
+ public void testPutintdouble() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ DoubleBuffer ret = buf.put(i, (double) i);
+ assertEquals(buf.get(i), (double) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ DoubleBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ // FIXME:
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500, 0.0);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Double") >= 0 || str.indexOf("double") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ void loadTestData1(double array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (double) i;
+ }
+ }
+
+ void loadTestData2(double array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (double) length - i;
+ }
+ }
+
+ void loadTestData1(DoubleBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (double) i);
+ }
+ }
+
+ void loadTestData2(DoubleBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (double) buf.capacity() - i);
+ }
+ }
+
+ private void assertContentEquals(DoubleBuffer buf, double array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i], 0.01);
+ }
+ }
+
+ private void assertContentEquals(DoubleBuffer buf, DoubleBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i), 0.01);
+ }
+ }
+
+ private void assertContentLikeTestData1(DoubleBuffer buf, int startIndex,
+ double startValue, int length) {
+ double value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value, 0.01);
+ value = value + 1.0;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
new file mode 100644
index 0000000..656241a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateDirectByteBufferTest.java
@@ -0,0 +1,31 @@
+/* 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.tests.java.nio;
+
+
+public class DuplicateDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
new file mode 100644
index 0000000..9f44d7a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateHeapByteBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+
+public class DuplicateHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
new file mode 100644
index 0000000..2796b88
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/DuplicateWrappedByteBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+
+public class DuplicateWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.duplicate();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
new file mode 100644
index 0000000..cfef096
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/FloatBufferTest.java
@@ -0,0 +1,674 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.DoubleBuffer;
+import java.nio.FloatBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.FloatBuffer
+ *
+ */
+public class FloatBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected FloatBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testArray() {
+ float array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ float array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ FloatBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0.0f, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1.0f, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ try {
+ buf.compareTo(null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+
+ FloatBuffer fbuffer1 = FloatBuffer.wrap(new float[] { Float.NaN });
+ FloatBuffer fbuffer2 = FloatBuffer.wrap(new float[] { Float.NaN });
+ FloatBuffer fbuffer3 = FloatBuffer.wrap(new float[] { 42f });
+
+ assertEquals("Failed equal comparison with NaN entry", 0, fbuffer1
+ .compareTo(fbuffer2));
+ assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer3
+ .compareTo(fbuffer1));
+ assertEquals("Failed greater than comparison with NaN entry", 1, fbuffer1
+ .compareTo(fbuffer3));
+
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ FloatBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ FloatBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for float get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer get(float[])
+ */
+ public void testGetfloatArray() {
+ float array[] = new float[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ FloatBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i), 0.01);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.get((float[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.get(new float[0]);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer get(float[], int, int)
+ */
+ public void testGetfloatArrayintint() {
+ buf.clear();
+ float array[] = new float[buf.capacity()];
+
+ try {
+ buf.get(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((float[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ FloatBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for float get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i), 0.01);
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ FloatBuffer readonly = buf.asReadOnlyBuffer();
+ FloatBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ if (buf.hasArray()) {
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float)
+ */
+ public void testPutfloat() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ FloatBuffer ret = buf.put((float) i);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float[])
+ */
+ public void testPutfloatArray() {
+ float array[] = new float[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (float) i;
+ FloatBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((float[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(float[], int, int)
+ */
+ public void testPutfloatArrayintint() {
+ buf.clear();
+ float array[] = new float[buf.capacity()];
+ try {
+ buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((float[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ FloatBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(java.nio.FloatBuffer)
+ */
+ public void testPutFloatBuffer() {
+ FloatBuffer other = FloatBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(FloatBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((FloatBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ buf.clear();
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ FloatBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.FloatBuffer put(int, float)
+ */
+ public void testPutintfloat() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ FloatBuffer ret = buf.put(i, (float) i);
+ assertEquals(buf.get(i), (float) i, 0.0);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ FloatBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500, 0.0);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Float") >= 0 || str.indexOf("float") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ void loadTestData1(float array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (float) i;
+ }
+ }
+
+ void loadTestData2(float array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (float) length - i;
+ }
+ }
+
+ void loadTestData1(FloatBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (float) i);
+ }
+ }
+
+ void loadTestData2(FloatBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (float) buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(FloatBuffer buf, float array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i], 0.01);
+ }
+ }
+
+ void assertContentEquals(FloatBuffer buf, FloatBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i), 0.01);
+ }
+ }
+
+ void assertContentLikeTestData1(FloatBuffer buf,
+ int startIndex, float startValue, int length) {
+ float value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value, 0.01);
+ value = value + 1.0f;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
new file mode 100644
index 0000000..2f8e44b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapByteBufferTest.java
@@ -0,0 +1,60 @@
+/* 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.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+
+public class HeapByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.allocate(BUFFER_LENGTH);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocate(int)
+ *
+ */
+ public void testAllocatedByteBuffer_IllegalArg() {
+ try {
+ ByteBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
new file mode 100644
index 0000000..a0c8d74
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapCharBufferTest.java
@@ -0,0 +1,44 @@
+/* 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.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class HeapCharBufferTest extends CharBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedCharBuffer_IllegalArg() {
+ try {
+ CharBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
new file mode 100644
index 0000000..2985899
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapDoubleBufferTest.java
@@ -0,0 +1,42 @@
+/* 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.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class HeapDoubleBufferTest extends DoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedDoubleBuffer_IllegalArg() {
+ try {
+ DoubleBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
new file mode 100644
index 0000000..f90b34e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapFloatBufferTest.java
@@ -0,0 +1,42 @@
+/* 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.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class HeapFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedFloatBuffer_IllegalArg() {
+ try {
+ FloatBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
new file mode 100644
index 0000000..0d68835
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapIntBufferTest.java
@@ -0,0 +1,42 @@
+/* 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.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class HeapIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedIntBuffer_IllegalArg() {
+ try {
+ IntBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
new file mode 100644
index 0000000..f4f2ae1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapLongBufferTest.java
@@ -0,0 +1,42 @@
+/* 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.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class HeapLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedLongBuffer_IllegalArg() {
+ try {
+ LongBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
new file mode 100644
index 0000000..327a035
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/HeapShortBufferTest.java
@@ -0,0 +1,42 @@
+/* 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.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class HeapShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testAllocatedShortBuffer_IllegalArg() {
+ try {
+ ShortBuffer.allocate(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
new file mode 100644
index 0000000..97babcf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/IntBufferTest.java
@@ -0,0 +1,650 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
+import java.nio.InvalidMarkException;
+
+/**
+ * Tests java.nio.IntBuffer
+ *
+ */
+public class IntBufferTest extends AbstractBufferTest {
+
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected IntBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testArray() {
+ int array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ int array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ IntBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ IntBuffer other = IntBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ IntBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ IntBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for int get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer get(int[])
+ */
+ public void testGetintArray() {
+ int array[] = new int[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ IntBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.get((int[])null);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer get(int[], int, int)
+ */
+ public void testGetintArrayintint() {
+ buf.clear();
+ int array[] = new int[buf.capacity()];
+
+ try {
+ buf.get(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((int[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ IntBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for int get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ IntBuffer readonly = buf.asReadOnlyBuffer();
+ IntBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int)
+ */
+ public void testPutint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ IntBuffer ret = buf.put((int) i);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int[])
+ */
+ public void testPutintArray() {
+ int array[] = new int[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (int) i;
+ IntBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((int[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int[], int, int)
+ */
+ public void testPutintArrayintint() {
+ buf.clear();
+ int array[] = new int[buf.capacity()];
+ try {
+ buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((int[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ IntBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(java.nio.IntBuffer)
+ */
+ public void testPutIntBuffer() {
+ IntBuffer other = IntBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(IntBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((IntBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ IntBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.IntBuffer put(int, int)
+ */
+ public void testPutintint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ IntBuffer ret = buf.put(i, (int) i);
+ assertEquals(buf.get(i), (int) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ IntBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Int") >= 0 || str.indexOf("int") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ void loadTestData1(int array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (int) i;
+ }
+ }
+
+ void loadTestData2(int array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (int) length - i;
+ }
+ }
+
+ void loadTestData1(IntBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (int) i);
+ }
+ }
+
+ void loadTestData2(IntBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (int) buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(IntBuffer buf, int array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(IntBuffer buf, IntBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(IntBuffer buf,
+ int startIndex, int startValue, int length) {
+ int value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = value + 1;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
new file mode 100644
index 0000000..4b7682d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/InvalidMarkExceptionTest.java
@@ -0,0 +1,51 @@
+/* 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.tests.java.nio;
+
+import java.nio.InvalidMarkException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class InvalidMarkExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new InvalidMarkException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new InvalidMarkException());
+ }
+
+ /**
+ *@tests {@link java.nio.InvalidMarkException#InvalidMarkException()}
+ */
+ public void test_Constructor() {
+ InvalidMarkException exception = new InvalidMarkException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getLocalizedMessage());
+ assertNull(exception.getCause());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
new file mode 100644
index 0000000..371351b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/LongBufferTest.java
@@ -0,0 +1,657 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.LongBuffer;
+
+/**
+ * Tests java.nio.LongBuffer
+ *
+ */
+public class LongBufferTest extends AbstractBufferTest {
+
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected LongBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testArray() {
+ long array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ long array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ LongBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ LongBuffer other = LongBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ LongBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ LongBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for long get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer get(long[])
+ */
+ public void testGetlongArray() {
+ long array[] = new long[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ LongBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.get((long[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer get(long[], int, int)
+ */
+ public void testGetlongArrayintint() {
+ buf.clear();
+ long array[] = new long[buf.capacity()];
+
+ try {
+ buf.get(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get((long[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ LongBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for long get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ LongBuffer readonly = buf.asReadOnlyBuffer();
+ LongBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long)
+ */
+ public void testPutlong() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ LongBuffer ret = buf.put((long) i);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long[])
+ */
+ public void testPutlongArray() {
+ long array[] = new long[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (long) i;
+ LongBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((long[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(long[], int, int)
+ */
+ public void testPutlongArrayintint() {
+ buf.clear();
+ long array[] = new long[buf.capacity()];
+ try {
+ buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((long[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ LongBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(java.nio.LongBuffer)
+ */
+ public void testPutLongBuffer() {
+ LongBuffer other = LongBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(LongBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((LongBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ LongBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.LongBuffer put(int, long)
+ */
+ public void testPutintlong() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ LongBuffer ret = buf.put(i, (long) i);
+ assertEquals(buf.get(i), (long) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ LongBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, 0, slice.capacity());
+ buf.put(2, 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Long") >= 0 || str.indexOf("long") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ void loadTestData1(long array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (long) i;
+ }
+ }
+
+ void loadTestData2(long array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (long) length - i;
+ }
+ }
+
+ void loadTestData1(LongBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (long) i);
+ }
+ }
+
+ void loadTestData2(LongBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (long) buf.capacity() - i);
+ }
+ }
+
+ void assertContentEquals(LongBuffer buf, long array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(LongBuffer buf, LongBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(LongBuffer buf,
+ int startIndex, long startValue, int length) {
+ long value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = value + 1;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java
new file mode 100644
index 0000000..308db21
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/MappedByteBufferTest.java
@@ -0,0 +1,231 @@
+/*
+ * 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.tests.java.nio;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.FileChannel.MapMode;
+
+import junit.framework.TestCase;
+
+public class MappedByteBufferTest extends TestCase {
+
+ File tmpFile, emptyFile;
+
+ /**
+ * A regression test for failing to correctly set capacity of underlying
+ * wrapped buffer from a mapped byte buffer.
+ */
+ public void testasIntBuffer() throws IOException {
+ // Map file
+ FileInputStream fis = new FileInputStream(tmpFile);
+ FileChannel fc = fis.getChannel();
+ MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc
+ .size());
+ int len = mmb.capacity();
+ assertEquals("Got wrong number of bytes", 46, len); //$NON-NLS-1$
+
+ // Read in our 26 bytes
+ for (int i = 0; i < 26; i++) {
+ byte b = mmb.get();
+ assertEquals("Got wrong byte value", (byte) 'A' + i, b); //$NON-NLS-1$
+ }
+
+ // Now convert to an IntBuffer to read our ints
+ IntBuffer ibuffer = mmb.asIntBuffer();
+ for (int i = 0; i < 5; i++) {
+ int val = ibuffer.get();
+ assertEquals("Got wrong int value", i + 1, val); //$NON-NLS-1$
+ }
+ fc.close();
+ }
+
+ /**
+ * Regression for HARMONY-6315 - FileChannel.map throws IOException
+ * when called with size 0
+ *
+ * @throws IOException
+ */
+ public void testEmptyBuffer() throws IOException {
+ // Map empty file
+ FileInputStream fis = new FileInputStream(emptyFile);
+ FileChannel fc = fis.getChannel();
+ MappedByteBuffer mmb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
+
+ // check non-null
+ assertNotNull("MappedByteBuffer created from empty file should not be null",
+ mmb);
+
+ // check capacity is 0
+ int len = mmb.capacity();
+ assertEquals("MappedByteBuffer created from empty file should have 0 capacity",
+ 0, len);
+
+ assertFalse("MappedByteBuffer from empty file shouldn't be backed by an array ",
+ mmb.hasArray());
+
+ try
+ {
+ byte b = mmb.get();
+ fail("Calling MappedByteBuffer.get() on empty buffer should throw a BufferUnderflowException");
+ }
+ catch (BufferUnderflowException e)
+ {
+ // expected behaviour
+ }
+
+ // test expected exceptions thrown
+ try
+ {
+ mmb = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
+ fail("Expected NonWritableChannelException to be thrown");
+ }
+ catch (NonWritableChannelException e)
+ {
+ // expected behaviour
+ }
+ try
+ {
+ mmb = fc.map(FileChannel.MapMode.PRIVATE, 0, fc.size());
+ fail("Expected NonWritableChannelException to be thrown");
+ }
+ catch (NonWritableChannelException e)
+ {
+ // expected behaviour
+ }
+ fc.close();
+ }
+
+ /**
+ * @tests {@link java.nio.MappedByteBuffer#force()}
+ */
+ public void test_force() throws IOException {
+ // buffer was not mapped in read/write mode
+ FileInputStream fileInputStream = new FileInputStream(tmpFile);
+ FileChannel fileChannelRead = fileInputStream.getChannel();
+ MappedByteBuffer mmbRead = fileChannelRead.map(MapMode.READ_ONLY, 0,
+ fileChannelRead.size());
+
+ mmbRead.force();
+
+ FileInputStream inputStream = new FileInputStream(tmpFile);
+ FileChannel fileChannelR = inputStream.getChannel();
+ MappedByteBuffer resultRead = fileChannelR.map(MapMode.READ_ONLY, 0,
+ fileChannelR.size());
+
+ //If this buffer was not mapped in read/write mode, then invoking this method has no effect.
+ assertEquals(
+ "Invoking force() should have no effect when this buffer was not mapped in read/write mode",
+ mmbRead, resultRead);
+
+ // Buffer was mapped in read/write mode
+ RandomAccessFile randomFile = new RandomAccessFile(tmpFile, "rw");
+ FileChannel fileChannelReadWrite = randomFile.getChannel();
+ MappedByteBuffer mmbReadWrite = fileChannelReadWrite.map(
+ FileChannel.MapMode.READ_WRITE, 0, fileChannelReadWrite.size());
+
+ mmbReadWrite.put((byte) 'o');
+ mmbReadWrite.force();
+
+ RandomAccessFile random = new RandomAccessFile(tmpFile, "rw");
+ FileChannel fileChannelRW = random.getChannel();
+ MappedByteBuffer resultReadWrite = fileChannelRW.map(
+ FileChannel.MapMode.READ_WRITE, 0, fileChannelRW.size());
+
+ // Invoking force() will change the buffer
+ assertFalse(mmbReadWrite.equals(resultReadWrite));
+
+ fileChannelRead.close();
+ fileChannelR.close();
+ fileChannelReadWrite.close();
+ fileChannelRW.close();
+ }
+
+ /**
+ * @tests {@link java.nio.MappedByteBuffer#load()}
+ */
+ public void test_load() throws IOException {
+ FileInputStream fileInputStream = new FileInputStream(tmpFile);
+ FileChannel fileChannelRead = fileInputStream.getChannel();
+ MappedByteBuffer mmbRead = fileChannelRead.map(MapMode.READ_ONLY, 0,
+ fileChannelRead.size());
+
+ assertEquals(mmbRead, mmbRead.load());
+
+ RandomAccessFile randomFile = new RandomAccessFile(tmpFile, "rw");
+ FileChannel fileChannelReadWrite = randomFile.getChannel();
+ MappedByteBuffer mmbReadWrite = fileChannelReadWrite.map(
+ FileChannel.MapMode.READ_WRITE, 0, fileChannelReadWrite.size());
+
+ assertEquals(mmbReadWrite, mmbReadWrite.load());
+
+ fileChannelRead.close();
+ fileChannelReadWrite.close();
+ }
+
+ protected void setUp() throws IOException {
+ // Create temp file with 26 bytes and 5 ints
+ tmpFile = File.createTempFile("harmony", "test"); //$NON-NLS-1$//$NON-NLS-2$
+ tmpFile.deleteOnExit();
+ FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
+ FileChannel fileChannel = fileOutputStream.getChannel();
+ ByteBuffer byteBuffer = ByteBuffer.allocateDirect(26 + 20);
+ for (int i = 0; i < 26; i++) {
+ byteBuffer.put((byte) ('A' + i));
+ }
+ for (int i = 0; i < 5; i++) {
+ byteBuffer.putInt(i + 1);
+ }
+ byteBuffer.rewind();
+ fileChannel.write(byteBuffer);
+ fileChannel.close();
+ fileOutputStream.close();
+
+ emptyFile = File.createTempFile("harmony", "test"); //$NON-NLS-1$//$NON-NLS-2$
+ emptyFile.deleteOnExit();
+ }
+
+ public void test_position() throws IOException {
+ File tmp = File.createTempFile("hmy", "tmp");
+ tmp.deleteOnExit();
+ RandomAccessFile f = new RandomAccessFile(tmp, "rw");
+ FileChannel ch = f.getChannel();
+ MappedByteBuffer mbb = ch.map(MapMode.READ_WRITE, 0L, 100L);
+ ch.close();
+
+ mbb.putInt(1, 1);
+ mbb.position(50);
+ mbb.putInt(50);
+
+ mbb.flip();
+ mbb.get();
+ assertEquals(1, mbb.getInt());
+
+ mbb.position(50);
+ assertEquals(50, mbb.getInt());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
new file mode 100644
index 0000000..cbacbc5
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyBufferExceptionTest.java
@@ -0,0 +1,51 @@
+/* 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.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+public class ReadOnlyBufferExceptionTest extends TestCase {
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ReadOnlyBufferException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ReadOnlyBufferException());
+ }
+
+ /**
+ *@tests {@link java.nio.ReadOnlyBufferException#ReadOnlyBufferException()}
+ */
+ public void test_Constructor() {
+ ReadOnlyBufferException exception = new ReadOnlyBufferException();
+ assertNull(exception.getMessage());
+ assertNull(exception.getLocalizedMessage());
+ assertNull(exception.getCause());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
new file mode 100644
index 0000000..f951962
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyCharBufferTest.java
@@ -0,0 +1,209 @@
+/* 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.tests.java.nio;
+
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyCharBufferTest extends CharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ }
+ }
+
+ public void testHashCode() {
+ CharBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutchar() {
+ try {
+ buf.put((char) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutcharArray() {
+ char array[] = new char[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutcharArrayintint() {
+ char array[] = new char[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((CharBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintchar() {
+ try {
+ buf.put(0, (char) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (char) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutStringintint() {
+ buf.clear();
+ String str = String.valueOf(new char[buf.capacity()]);
+ try {
+ buf.put(str, 0, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((String) null, 0, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException expected) {
+ } catch (NullPointerException expected) {
+ }
+ try {
+ buf.put(str, -1, str.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException expected) {
+ } catch (NullPointerException expected) {
+ }
+ String longStr = String.valueOf(new char[buf.capacity()+1]);
+ try {
+ buf.put(longStr, 0, longStr.length());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutString() {
+ String str = " ";
+ try {
+ buf.put(str);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((String)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
new file mode 100644
index 0000000..20c7914
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDirectByteBufferTest.java
@@ -0,0 +1,44 @@
+/* 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.tests.java.nio;
+
+
+public class ReadOnlyDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
new file mode 100644
index 0000000..d87e81d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyDoubleBufferTest.java
@@ -0,0 +1,160 @@
+/* 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.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyDoubleBufferTest extends DoubleBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ }
+ }
+
+ public void testHashCode() {
+ DoubleBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutdouble() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutdoubleArray() {
+ double array[] = new double[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((double[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutdoubleArrayintint() {
+ double array[] = new double[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((double[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new double[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutDoubleBuffer() {
+ DoubleBuffer other = DoubleBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((DoubleBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintdouble() {
+ try {
+ buf.put(0, (double) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (double) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
new file mode 100644
index 0000000..3acc5c4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyFloatBufferTest.java
@@ -0,0 +1,161 @@
+/* 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.tests.java.nio;
+
+import java.nio.FloatBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ FloatBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloat() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloatArray() {
+ float array[] = new float[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((float[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutfloatArrayintint() {
+ float array[] = new float[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((float[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new float[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutFloatBuffer() {
+ FloatBuffer other = FloatBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((FloatBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintfloat() {
+ try {
+ buf.put(0, (float) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (float) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
new file mode 100644
index 0000000..7452a24
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapByteBufferTest.java
@@ -0,0 +1,43 @@
+/* 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.tests.java.nio;
+
+
+public class ReadOnlyHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
new file mode 100644
index 0000000..4c7792a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapCharBufferTest.java
@@ -0,0 +1,35 @@
+/* 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.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+
+public class ReadOnlyHeapCharBufferTest extends ReadOnlyCharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
new file mode 100644
index 0000000..f95c4c2
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapDoubleBufferTest.java
@@ -0,0 +1,34 @@
+/* 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.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyHeapDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
new file mode 100644
index 0000000..f2c6644
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyHeapFloatBufferTest extends ReadOnlyFloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
new file mode 100644
index 0000000..f9a3877
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapIntBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyHeapIntBufferTest extends ReadOnlyIntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
new file mode 100644
index 0000000..efba978
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapLongBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyHeapLongBufferTest extends ReadOnlyLongBufferTest{
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
new file mode 100644
index 0000000..bbbd616
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyHeapShortBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyHeapShortBufferTest extends ReadOnlyShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
new file mode 100644
index 0000000..61e78a6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyIntBufferTest.java
@@ -0,0 +1,161 @@
+/* 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.tests.java.nio;
+
+import java.nio.IntBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ IntBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutint() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintArray() {
+ int array[] = new int[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((int[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutintArrayintint() {
+ int array[] = new int[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((int[]) null, -1, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new int[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutIntBuffer() {
+ IntBuffer other = IntBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((IntBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintint() {
+ try {
+ buf.put(0, (int) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (int) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
new file mode 100644
index 0000000..b670606
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyLongBufferTest.java
@@ -0,0 +1,161 @@
+/* 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.tests.java.nio;
+
+import java.nio.LongBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class ReadOnlyLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ LongBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutlong() {
+ try {
+ buf.put(0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutlongArray() {
+ long array[] = new long[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((long[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutlongArrayintint() {
+ long array[] = new long[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((long[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new long[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutLongBuffer() {
+ LongBuffer other = LongBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((LongBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintlong() {
+ try {
+ buf.put(0, (long) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (long) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
new file mode 100644
index 0000000..611f6bf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyShortBufferTest.java
@@ -0,0 +1,161 @@
+/* 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.tests.java.nio;
+
+import java.nio.ReadOnlyBufferException;
+import java.nio.ShortBuffer;
+
+public class ReadOnlyShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ //expected
+ }
+ }
+
+ public void testHashCode() {
+ ShortBuffer duplicate = buf.duplicate();
+ assertEquals(buf.hashCode(), duplicate.hashCode());
+ }
+
+ public void testArrayOffset() {
+ try {
+ buf.arrayOffset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ //expected
+ }
+ }
+
+ public void testCompact() {
+ try {
+ buf.compact();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutshort() {
+ try {
+ buf.put((short)0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutshortArray() {
+ short array[] = new short[1];
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((short[]) null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testPutshortArrayintint() {
+ short array[] = new short[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((short[]) null, 0, 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutShortBuffer() {
+ ShortBuffer other = ShortBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((ShortBuffer) null);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(buf);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+
+ public void testPutintshort() {
+ try {
+ buf.put(0, (short) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put(-1, (short) 0);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
new file mode 100644
index 0000000..031d75b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedByteBufferTest.java
@@ -0,0 +1,45 @@
+/* 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.tests.java.nio;
+
+
+public class ReadOnlyWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testIsReadOnly() {
+ assertTrue(buf.isReadOnly());
+ }
+
+ public void testHasArray() {
+ assertFalse(buf.hasArray());
+ }
+
+ public void testHashCode() {
+ super.readOnlyHashCode();
+ }
+
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
new file mode 100644
index 0000000..57c04bf
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedCharBufferTest1.java
@@ -0,0 +1,34 @@
+/* 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.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class ReadOnlyWrappedCharBufferTest1 extends ReadOnlyCharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
new file mode 100644
index 0000000..d1ba9df
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedDoubleBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class ReadOnlyWrappedDoubleBufferTest extends ReadOnlyDoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
new file mode 100644
index 0000000..affddaa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedFloatBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class ReadOnlyWrappedFloatBufferTest extends ReadOnlyFloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
new file mode 100644
index 0000000..a4d0155
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedIntBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class ReadOnlyWrappedIntBufferTest extends ReadOnlyIntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
new file mode 100644
index 0000000..58491da
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedLongBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class ReadOnlyWrappedLongBufferTest extends ReadOnlyLongBufferTest{
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
new file mode 100644
index 0000000..0ecb3a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ReadOnlyWrappedShortBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class ReadOnlyWrappedShortBufferTest extends ReadOnlyShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+ super.loadTestData1(buf);
+ buf = buf.asReadOnlyBuffer();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
new file mode 100644
index 0000000..98d7659
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/ShortBufferTest.java
@@ -0,0 +1,637 @@
+/*
+ * 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteOrder;
+import java.nio.InvalidMarkException;
+import java.nio.ShortBuffer;
+
+/**
+ * Tests java.nio.ShortBuffer
+ *
+ */
+public class ShortBufferTest extends AbstractBufferTest {
+
+ protected static final int SMALL_TEST_LENGTH = 5;
+
+ protected static final int BUFFER_LENGTH = 20;
+
+ protected ShortBuffer buf;
+
+ protected void setUp() throws Exception {
+ buf = ShortBuffer.allocate(BUFFER_LENGTH);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ buf = null;
+ baseBuf = null;
+ }
+
+ public void testArray() {
+ short array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testArrayOffset() {
+ short array[] = buf.array();
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(array, buf.arrayOffset(), buf.capacity());
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData1(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+
+ loadTestData2(buf);
+ assertContentEquals(buf, array, buf.arrayOffset(), buf.capacity());
+ }
+
+ public void testAsReadOnlyBuffer() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // readonly's contents should be the same as buf
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ assertNotSame(buf, readonly);
+ assertTrue(readonly.isReadOnly());
+ assertEquals(buf.position(), readonly.position());
+ assertEquals(buf.limit(), readonly.limit());
+ assertEquals(buf.isDirect(), readonly.isDirect());
+ assertEquals(buf.order(), readonly.order());
+ assertContentEquals(buf, readonly);
+
+ // readonly's position, mark, and limit should be independent to buf
+ readonly.reset();
+ assertEquals(readonly.position(), 0);
+ readonly.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+ }
+
+ public void testCompact() {
+ // case: buffer is full
+ buf.clear();
+ buf.mark();
+ loadTestData1(buf);
+ ShortBuffer ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), buf.capacity());
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: buffer is empty
+ buf.position(0);
+ buf.limit(0);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 0);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 0, buf.capacity());
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // case: normal
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(5);
+ buf.mark();
+ ret = buf.compact();
+ assertSame(ret, buf);
+ assertEquals(buf.position(), 4);
+ assertEquals(buf.limit(), buf.capacity());
+ assertContentLikeTestData1(buf, 0, (short) 1, 4);
+ try {
+ buf.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+ }
+
+ public void testCompareTo() {
+ // compare to self
+ assertEquals(0, buf.compareTo(buf));
+
+ // normal cases
+ assertTrue(buf.capacity() > 5);
+ buf.clear();
+ ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+ loadTestData1(other);
+ assertEquals(0, buf.compareTo(other));
+ assertEquals(0, other.compareTo(buf));
+ buf.position(1);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ other.position(2);
+ assertTrue(buf.compareTo(other) < 0);
+ assertTrue(other.compareTo(buf) > 0);
+ buf.position(2);
+ other.limit(5);
+ assertTrue(buf.compareTo(other) > 0);
+ assertTrue(other.compareTo(buf) < 0);
+ }
+
+ public void testDuplicate() {
+ buf.clear();
+ buf.mark();
+ buf.position(buf.limit());
+
+ // duplicate's contents should be the same as buf
+ ShortBuffer duplicate = buf.duplicate();
+ assertNotSame(buf, duplicate);
+ assertEquals(buf.position(), duplicate.position());
+ assertEquals(buf.limit(), duplicate.limit());
+ assertEquals(buf.isReadOnly(), duplicate.isReadOnly());
+ assertEquals(buf.isDirect(), duplicate.isDirect());
+ assertEquals(buf.order(), duplicate.order());
+ assertContentEquals(buf, duplicate);
+
+ // duplicate's position, mark, and limit should be independent to buf
+ duplicate.reset();
+ assertEquals(duplicate.position(), 0);
+ duplicate.clear();
+ assertEquals(buf.position(), buf.limit());
+ buf.reset();
+ assertEquals(buf.position(), 0);
+
+ // duplicate share the same content with buf
+ if (!duplicate.isReadOnly()) {
+ loadTestData1(buf);
+ assertContentEquals(buf, duplicate);
+ loadTestData2(duplicate);
+ assertContentEquals(buf, duplicate);
+ }
+ }
+
+ public void testEquals() {
+ // equal to self
+ assertTrue(buf.equals(buf));
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ assertTrue(buf.equals(readonly));
+ ShortBuffer duplicate = buf.duplicate();
+ assertTrue(buf.equals(duplicate));
+
+ // always false, if type mismatch
+ assertFalse(buf.equals(Boolean.TRUE));
+
+ assertTrue(buf.capacity() > 5);
+
+ buf.limit(buf.capacity()).position(0);
+ readonly.limit(readonly.capacity()).position(1);
+ assertFalse(buf.equals(readonly));
+
+ buf.limit(buf.capacity() - 1).position(0);
+ duplicate.limit(duplicate.capacity()).position(0);
+ assertFalse(buf.equals(duplicate));
+ }
+
+ /*
+ * Class under test for short get()
+ */
+ public void testGet() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer get(short[])
+ */
+ public void testGetshortArray() {
+ short array[] = new short[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ShortBuffer ret = buf.get(array);
+ assertEquals(array[0], buf.get(i));
+ assertSame(ret, buf);
+ }
+ try {
+ buf.get(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer get(short[], int, int)
+ */
+ public void testGetshortArrayintint() {
+ buf.clear();
+ short array[] = new short[buf.capacity()];
+
+ try {
+ buf.get(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.get(array, array.length, 0);
+ try {
+ buf.get(array, array.length + 1, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.get((short[])null, 2, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferUnderflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ buf.get(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+
+ buf.clear();
+ ShortBuffer ret = buf.get(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for short get(int)
+ */
+ public void testGetint() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ assertEquals(buf.get(), buf.get(i));
+ }
+ try {
+ buf.get(-1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.get(buf.limit());
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testHasArray() {
+ assertNotNull(buf.array());
+ }
+
+ public void testHashCode() {
+ buf.clear();
+ ShortBuffer readonly = buf.asReadOnlyBuffer();
+ ShortBuffer duplicate = buf.duplicate();
+ assertTrue(buf.hashCode() == readonly.hashCode());
+
+ assertTrue(buf.capacity() > 5);
+ duplicate.position(buf.capacity() / 2);
+ assertTrue(buf.hashCode() != duplicate.hashCode());
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testOrder() {
+ buf.order();
+ assertEquals(ByteOrder.nativeOrder(), buf.order());
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short)
+ */
+ public void testPutshort() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ ShortBuffer ret = buf.put((short) i);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put((short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short[])
+ */
+ public void testPutshortArray() {
+ short array[] = new short[1];
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), i);
+ array[0] = (short) i;
+ ShortBuffer ret = buf.put(array);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(array);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.position(buf.limit());
+ buf.put((short[])null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(short[], int, int)
+ */
+ public void testPutshortArrayintint() {
+ buf.clear();
+ short array[] = new short[buf.capacity()];
+ try {
+ buf.put(new short[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, array.length + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ buf.put(array, array.length, 0);
+ assertEquals(buf.position(), 0);
+ try {
+ buf.put(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put((short[])null, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 2, array.length);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ assertEquals(buf.position(), 0);
+
+ loadTestData2(array, 0, array.length);
+ ShortBuffer ret = buf.put(array, 0, array.length);
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(buf, array, 0, array.length);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(java.nio.ShortBuffer)
+ */
+ public void testPutShortBuffer() {
+ ShortBuffer other = ShortBuffer.allocate(buf.capacity());
+ try {
+ buf.put(buf);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ buf.put(ShortBuffer.allocate(buf.capacity() + 1));
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (BufferOverflowException e) {
+ // expected
+ }
+ try {
+ buf.flip();
+ buf.put((ShortBuffer)null);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ loadTestData2(other);
+ other.clear();
+ buf.clear();
+ ShortBuffer ret = buf.put(other);
+ assertEquals(other.position(), other.capacity());
+ assertEquals(buf.position(), buf.capacity());
+ assertContentEquals(other, buf);
+ assertSame(ret, buf);
+ }
+
+ /*
+ * Class under test for java.nio.ShortBuffer put(int, short)
+ */
+ public void testPutintshort() {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.position(), 0);
+ ShortBuffer ret = buf.put(i, (short) i);
+ assertEquals(buf.get(i), (short) i);
+ assertSame(ret, buf);
+ }
+ try {
+ buf.put(-1, (short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ buf.put(buf.limit(), (short) 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ }
+
+ public void testSlice() {
+ assertTrue(buf.capacity() > 5);
+ buf.position(1);
+ buf.limit(buf.capacity() - 1);
+
+ ShortBuffer slice = buf.slice();
+ assertEquals(buf.isReadOnly(), slice.isReadOnly());
+ assertEquals(buf.isDirect(), slice.isDirect());
+ assertEquals(buf.order(), slice.order());
+ assertEquals(slice.position(), 0);
+ assertEquals(slice.limit(), buf.remaining());
+ assertEquals(slice.capacity(), buf.remaining());
+ try {
+ slice.reset();
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (InvalidMarkException e) {
+ // expected
+ }
+
+ // slice share the same content with buf
+ if (!slice.isReadOnly()) {
+ loadTestData1(slice);
+ assertContentLikeTestData1(buf, 1, (short) 0, slice.capacity());
+ buf.put(2, (short) 500);
+ assertEquals(slice.get(1), 500);
+ }
+ }
+
+ public void testToString() {
+ String str = buf.toString();
+ assertTrue(str.indexOf("Short") >= 0 || str.indexOf("short") >= 0);
+ assertTrue(str.indexOf("" + buf.position()) >= 0);
+ assertTrue(str.indexOf("" + buf.limit()) >= 0);
+ assertTrue(str.indexOf("" + buf.capacity()) >= 0);
+ }
+
+ void loadTestData1(short array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (short) i;
+ }
+ }
+
+ void loadTestData2(short array[], int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ array[offset + i] = (short) (length - i);
+ }
+ }
+
+ void loadTestData1(ShortBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (short) i);
+ }
+ }
+
+ void loadTestData2(ShortBuffer buf) {
+ buf.clear();
+ for (int i = 0; i < buf.capacity(); i++) {
+ buf.put(i, (short) (buf.capacity() - i));
+ }
+ }
+
+ void assertContentEquals(ShortBuffer buf, short array[],
+ int offset, int length) {
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(i), array[offset + i]);
+ }
+ }
+
+ void assertContentEquals(ShortBuffer buf, ShortBuffer other) {
+ assertEquals(buf.capacity(), other.capacity());
+ for (int i = 0; i < buf.capacity(); i++) {
+ assertEquals(buf.get(i), other.get(i));
+ }
+ }
+
+ void assertContentLikeTestData1(ShortBuffer buf,
+ int startIndex, short startValue, int length) {
+ short value = startValue;
+ for (int i = 0; i < length; i++) {
+ assertEquals(buf.get(startIndex + i), value);
+ value = (short) (value + 1);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
new file mode 100644
index 0000000..541cde0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceDirectByteBufferTest.java
@@ -0,0 +1,32 @@
+/* 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.tests.java.nio;
+
+
+public class SliceDirectByteBufferTest extends DirectByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
new file mode 100644
index 0000000..9f9f7aa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceHeapByteBufferTest.java
@@ -0,0 +1,33 @@
+/* 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.tests.java.nio;
+
+
+public class SliceHeapByteBufferTest extends HeapByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
new file mode 100644
index 0000000..f1ddfb9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/SliceWrappedByteBufferTest.java
@@ -0,0 +1,33 @@
+/* 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.tests.java.nio;
+
+
+public class SliceWrappedByteBufferTest extends WrappedByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf.position(1).limit(BUFFER_LENGTH-1);
+ buf = buf.slice();
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.java
new file mode 100644
index 0000000..6460d2e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedByteBufferTest.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.
+ */
+
+package org.apache.harmony.nio.tests.java.nio;
+
+import java.nio.ByteBuffer;
+
+public class WrappedByteBufferTest extends ByteBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ByteBuffer.wrap(new byte[BUFFER_LENGTH]);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ buf = null;
+ baseBuf = null;
+ }
+
+ /**
+ * @tests java.nio.ByteBuffer#allocate(byte[],int,int)
+ *
+ */
+ public void testWrappedByteBuffer_IllegalArg() {
+ byte array[] = new byte[BUFFER_LENGTH];
+ try {
+ ByteBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ByteBuffer.wrap((byte[])null, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testIsDirect() {
+ assertFalse(buf.isDirect());
+ }
+
+ public void testHasArray() {
+ assertTrue(buf.hasArray());
+ }
+
+ public void testIsReadOnly() {
+ assertFalse(buf.isReadOnly());
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
new file mode 100644
index 0000000..9181a77
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest1.java
@@ -0,0 +1,84 @@
+/* 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.tests.java.nio;
+
+import java.nio.CharBuffer;
+
+public class WrappedCharBufferTest1 extends CharBufferTest {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(new char[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedCharBuffer_IllegalArg() {
+ char array[] = new char[BUFFER_LENGTH];
+ try {
+ CharBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, BUFFER_LENGTH + 1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 0, BUFFER_LENGTH + 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap((char[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
new file mode 100644
index 0000000..5fa9335
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedCharBufferTest2.java
@@ -0,0 +1,128 @@
+/* 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.tests.java.nio;
+
+import java.nio.BufferOverflowException;
+import java.nio.CharBuffer;
+import java.nio.ReadOnlyBufferException;
+
+public class WrappedCharBufferTest2 extends ReadOnlyCharBufferTest {
+ protected static final String TEST_STRING = "123456789abcdef12345";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = CharBuffer.wrap(TEST_STRING);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ public void testWrappedCharSequence_IllegalArg() {
+ String str = TEST_STRING;
+ try {
+ CharBuffer.wrap(str, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 21, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 2, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap(str, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ CharBuffer.wrap((String)null, -1, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void testArray() {
+ try {
+ buf.array();
+ fail("Should throw UnsupportedOperationException"); //$NON-NLS-1$
+ } catch (UnsupportedOperationException e) {
+ }
+ }
+
+ public void testPutcharArrayintint() {
+ char array[] = new char[1];
+ try {
+ buf.put(array, 0, array.length);
+ fail("Should throw ReadOnlyBufferException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException e) {
+ // expected
+ }
+ try {
+ buf.put((char[]) null, 0, 1);
+ fail("Should throw NullPointerException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException expected) {
+ } catch (NullPointerException expected) {
+ }
+ try {
+ buf.put(new char[buf.capacity() + 1], 0, buf.capacity() + 1);
+ fail("Should throw BufferOverflowException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException expected) {
+ } catch (BufferOverflowException expected) {
+ }
+ try {
+ buf.put(array, -1, array.length);
+ fail("Should throw IndexOutOfBoundsException"); //$NON-NLS-1$
+ } catch (ReadOnlyBufferException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ }
+
+ public void testPutCharBuffer() {
+ CharBuffer other = CharBuffer.allocate(1);
+ try {
+ buf.put(other);
+ fail();
+ } catch (ReadOnlyBufferException expected) {
+ }
+ try {
+ buf.put((CharBuffer) null);
+ fail();
+ } catch (ReadOnlyBufferException expected) {
+ } catch (NullPointerException expected) {
+ }
+ try {
+ buf.put(buf);
+ fail();
+ } catch (ReadOnlyBufferException expected) {
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
new file mode 100644
index 0000000..f970849
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedDoubleBufferTest.java
@@ -0,0 +1,87 @@
+/* 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.tests.java.nio;
+
+import java.nio.DoubleBuffer;
+
+public class WrappedDoubleBufferTest extends DoubleBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = DoubleBuffer.wrap(new double[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedDoubleuffer_IllegalArg() {
+ double array[] = new double[20];
+ try {
+ DoubleBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ DoubleBuffer.wrap((double[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ DoubleBuffer buf = DoubleBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
new file mode 100644
index 0000000..43b13c3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedFloatBufferTest.java
@@ -0,0 +1,87 @@
+/* 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.tests.java.nio;
+
+import java.nio.FloatBuffer;
+
+public class WrappedFloatBufferTest extends FloatBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = FloatBuffer.wrap(new float[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedFloatBuffer_IllegalArg() {
+ float array[] = new float[20];
+ try {
+ FloatBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ FloatBuffer.wrap((float[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ FloatBuffer buf = FloatBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
new file mode 100644
index 0000000..383e964
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedIntBufferTest.java
@@ -0,0 +1,87 @@
+/* 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.tests.java.nio;
+
+import java.nio.IntBuffer;
+
+public class WrappedIntBufferTest extends IntBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = IntBuffer.wrap(new int[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedIntBuffer_IllegalArg() {
+ int array[] = new int[20];
+ try {
+ IntBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ IntBuffer.wrap((int[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ IntBuffer buf = IntBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
new file mode 100644
index 0000000..581c912
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedLongBufferTest.java
@@ -0,0 +1,87 @@
+/* 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.tests.java.nio;
+
+import java.nio.LongBuffer;
+
+public class WrappedLongBufferTest extends LongBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = LongBuffer.wrap(new long[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedLongBuffer_IllegalArg() {
+ long array[] = new long[20];
+ try {
+ LongBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ LongBuffer.wrap((long[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ LongBuffer buf = LongBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
new file mode 100644
index 0000000..9c6f781
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/WrappedShortBufferTest.java
@@ -0,0 +1,87 @@
+/* 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.tests.java.nio;
+
+import java.nio.ShortBuffer;
+
+public class WrappedShortBufferTest extends ShortBufferTest {
+ protected void setUp() throws Exception {
+ super.setUp();
+ buf = ShortBuffer.wrap(new short[BUFFER_LENGTH]);
+ loadTestData1(buf);
+ baseBuf = buf;
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ baseBuf = null;
+ buf = null;
+ }
+
+ /**
+ * @tests java.nio.CharBuffer#allocate(char[],int,int)
+ *
+ */
+ public void testWrappedShortBuffer_IllegalArg() {
+ short array[] = new short[20];
+ try {
+ ShortBuffer.wrap(array, -1, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 21, 0);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 0, -1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 0, 21);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, Integer.MAX_VALUE, 1);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap(array, 1, Integer.MAX_VALUE);
+ fail("Should throw Exception"); //$NON-NLS-1$
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ ShortBuffer.wrap((short[])null, -1, 0);
+ fail("Should throw NPE"); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ }
+
+ ShortBuffer buf = ShortBuffer.wrap(array, 2, 16);
+ assertEquals(buf.position(), 2);
+ assertEquals(buf.limit(), 18);
+ assertEquals(buf.capacity(), 20);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
new file mode 100644
index 0000000..ac820a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AlreadyConnectedExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.AlreadyConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AlreadyConnectedException
+ */
+public class AlreadyConnectedExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.AlreadyConnectedException#AlreadyConnectedException()}
+ */
+ public void test_Constructor() {
+ AlreadyConnectedException e = new AlreadyConnectedException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new AlreadyConnectedException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new AlreadyConnectedException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
new file mode 100644
index 0000000..123eb1f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/AsynchronousCloseExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.AsynchronousCloseException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for AsynchronousCloseException
+ */
+public class AsynchronousCloseExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.AsynchronousCloseException#AsynchronousCloseException()}
+ */
+ public void test_Constructor() {
+ AsynchronousCloseException e = new AsynchronousCloseException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new AsynchronousCloseException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new AsynchronousCloseException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
new file mode 100644
index 0000000..7a73322
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/CancelledKeyExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.CancelledKeyException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for CancelledKeyException
+ */
+public class CancelledKeyExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.CancelledKeyException#CancelledKeyException()}
+ */
+ public void test_Constructor() {
+ CancelledKeyException e = new CancelledKeyException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CancelledKeyException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new CancelledKeyException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
new file mode 100644
index 0000000..4223fb8
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ChannelsTest.java
@@ -0,0 +1,622 @@
+/* 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.tests.java.nio.channels;
+
+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.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.charset.Charset;
+import java.nio.charset.UnsupportedCharsetException;
+
+import tests.support.Support_PortManager;
+
+import junit.framework.TestCase;
+
+/**
+ * Note: the test case uses a temp text file named "test" which contains 31
+ * characters : "P@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]"
+ *
+ */
+
+public class ChannelsTest extends TestCase {
+ private static final String CODE_SET = "GB2312"; //$NON-NLS-1$
+
+ private static final String BAD_CODE_SET = "GB2313"; //$NON-NLS-1$
+
+ private FileInputStream fins;
+
+ private FileOutputStream fouts;
+
+ private final int writebufSize = 60;
+
+ private final int testNum = 10;
+
+ private final int fileSize = 31;// the file size
+
+ private File tmpFile;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ // Make the test file same in every test
+ tmpFile = File.createTempFile("test","tmp");
+ tmpFile.deleteOnExit();
+ this.writeFileSame();
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.fins) {
+ this.fins.close();
+ this.fins = null;
+ }
+ if (null != this.fouts) {
+ this.fouts.close();
+ this.fouts = null;
+ }
+
+ tmpFile.delete();
+ super.tearDown();
+
+ }
+
+ private void writeFileSame() throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.fouts.flush();
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ this.fouts.write(writebuf.getBytes());
+ }
+
+ /*
+ * This private method is to assert if the file size is the same as the
+ * compare Number in the test
+ */
+ private void assertFileSizeSame(File fileToTest, int compareNumber)
+ throws IOException {
+ FileInputStream file = new FileInputStream(fileToTest);
+ assertEquals(file.available(), compareNumber);
+ file.close();
+ }
+
+ // test if new Channel to input is null
+ public void testNewChannelInputStream_InputNull() throws IOException {
+ ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+ this.fins = null;
+ int readres = this.testNum;
+ try {
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ assertNotNull(rbChannel);
+ readres = rbChannel.read(byteBuf);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ assertEquals(this.testNum, readres);
+ }
+
+ // test if buffer to read is null
+ public void testNewChannelInputStream_BufferNull() throws IOException {
+ ByteBuffer byteBuf = ByteBuffer.allocate(this.testNum);
+ int readres = this.testNum;
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ assertNotNull(rbChannel);
+ try {
+ readres = rbChannel.read(null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(this.testNum, readres);
+ readres = 0;
+ try {
+ readres = rbChannel.read(byteBuf);
+ } catch (NullPointerException e) {
+ fail();
+ }
+ assertEquals(this.testNum, readres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.Channels.NewChannel'
+ */
+ public void testNewChannelInputStream() throws IOException {
+ int bufSize = 10;
+ int readres = 0;
+ byte[] byteArray = new byte[bufSize];
+ ByteBuffer byteBuf = ByteBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ readres = this.fins.read(byteArray);
+
+ assertEquals(bufSize, readres);
+ assertFalse(0 == this.fins.available());
+
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ // fins still reads.
+ assertFalse(0 == this.fins.available());
+ readres = this.fins.read(byteArray);
+ assertEquals(bufSize, readres);
+
+ // rbChannel also reads.
+ assertNotNull(rbChannel);
+ readres = rbChannel.read(byteBuf);
+
+ assertEquals(bufSize, readres);
+ InputStream ins = Channels.newInputStream(rbChannel);
+ assertNotNull(ins);
+ assertEquals(0, ins.available());
+ }
+
+ // test if fout to change is null
+ public void testNewChannelOutputStream_inputNull() throws IOException {
+ int writeres = this.testNum;
+ ByteBuffer writebuf = ByteBuffer.allocate(this.writebufSize);
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf.putChar((char) (val + 64));
+ }
+ this.fouts = null;
+ try {
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+ writeres = rbChannel.write(writebuf);
+ assertEquals(0, writeres);
+
+ writebuf.flip();
+ writeres = rbChannel.write(writebuf);
+ fail("Should throw NPE.");
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ // test if write buf is null
+ public void testNewChannelOutputStream_BufNull() throws IOException {
+ int writeres = this.testNum;
+ ByteBuffer writebuf = null;
+ try {
+ this.fouts = new FileOutputStream(tmpFile);
+ } catch (FileNotFoundException e) {
+ fail();
+ }
+
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+ try {
+ writeres = rbChannel.write(writebuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(this.testNum, writeres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.Channels.NewChannel(OutputStream)'
+ */
+ public void testNewChannelOutputStream() throws IOException {
+ int writeNum = 0;
+ ByteBuffer writebuf = ByteBuffer.allocateDirect(this.writebufSize);
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf.putChar((char) (val + 64));
+ }
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel testChannel = this.fouts.getChannel();
+ WritableByteChannel rbChannel = Channels.newChannel(this.fouts);
+
+ assertTrue(testChannel.isOpen());
+ assertTrue(rbChannel.isOpen());
+
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.fouts.flush();
+ this.fins = new FileInputStream(tmpFile);
+ assertEquals(this.fins.available(), 1);
+ this.fins.close();
+
+ writeNum = rbChannel.write(writebuf);
+ // write success ,but output null
+ assertEquals(0, writeNum);
+ // close of fouts does not affect on channel
+ this.fouts.close();
+ writeNum = rbChannel.write(writebuf);
+ assertEquals(0, writeNum);
+ try {
+ writeNum = testChannel.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertEquals(0, writeNum);
+ // close of rbchannel does affect on testchannel(same channel)
+ rbChannel.close();
+ try {
+ writeNum = testChannel.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testNewInputStreamReadableByteChannel_InputNull()
+ throws Exception {
+ byte[] readbuf = new byte[this.testNum];
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel readbc = this.fins.getChannel();
+ assertEquals(this.fileSize, this.fins.available());
+ assertTrue(readbc.isOpen());
+
+ try {
+ InputStream testins = Channels.newInputStream(null);
+ assertNotNull(testins);
+ testins.read(readbuf);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNewInputStreamReadableByteChannel() throws Exception {
+ ByteBuffer readbcbuf = ByteBuffer.allocateDirect(this.testNum);
+ byte[] readbuf = new byte[this.testNum];
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel readbc = this.fins.getChannel();
+ assertEquals(this.fileSize, this.fins.available());
+ assertTrue(readbc.isOpen());
+ InputStream testins = Channels.newInputStream(readbc);
+ // read in testins and fins use the same pointer
+ testins.read(readbuf);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum);
+ int readNum = readbc.read(readbcbuf);
+ assertEquals(readNum, this.testNum);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum * 2);
+ testins.read(readbuf);
+ assertEquals(this.fins.available(), this.fileSize - this.testNum * 3);
+ // readbc.close() affect testins
+ readbc.close();
+ assertFalse(readbc.isOpen());
+ try {
+ testins.read(readbuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testNewOutputStreamWritableByteChannel_InputNull()
+ throws Exception {
+ byte[] writebuf = new byte[this.testNum];
+ try {
+ OutputStream testouts = Channels.newOutputStream(null);
+ assertNotNull(testouts);
+ testouts.write(writebuf);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ WritableByteChannel writebc = Channels.newChannel((OutputStream) null);
+ assertTrue(writebc.isOpen());
+ OutputStream testoutputS = Channels.newOutputStream(writebc);
+ testoutputS.write(writebuf);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testNewOutputStreamWritableByteChannel() throws Exception {
+ byte[] writebuf = new byte[this.testNum];
+ ByteBuffer writebcbuf = ByteBuffer.allocateDirect(this.testNum);
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel writebc = this.fouts.getChannel();
+
+ assertTrue(writebc.isOpen());
+ OutputStream testouts = Channels.newOutputStream(writebc);
+
+ // read in testins and fins use the same pointer
+ testouts.write(writebuf);
+ this.assertFileSizeSame(tmpFile, this.testNum);
+ writebc.write(writebcbuf);
+ this.assertFileSizeSame(tmpFile, this.testNum * 2);
+ testouts.write(writebuf);
+ this.assertFileSizeSame(tmpFile, this.testNum * 3);
+ // readbc.close() affect testins
+ writebc.close();
+ assertFalse(writebc.isOpen());
+ try {
+ testouts.write(writebuf);
+ fail();
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testnewReaderCharsetError() throws Exception {
+ this.fins = new FileInputStream(tmpFile);
+
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ try {
+ Channels.newReader(rbChannel, Charset.forName(BAD_CODE_SET)
+ .newDecoder(), //$NON-NLS-1$
+ -1);
+ fail();
+ } catch (UnsupportedCharsetException e) {
+ // correct
+ }
+ }
+
+ public void testnewWriterCharsetError() throws Exception {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ try {
+ Channels.newWriter(wbChannel, Charset.forName(BAD_CODE_SET)
+ .newEncoder(), -1);
+ fail();
+ } catch (UnsupportedCharsetException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString_InputNull()
+ throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ // channel null
+ Reader testReader;
+ try {
+ testReader = Channels.newReader(null, Charset.forName(CODE_SET).newDecoder(), -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, readres);
+
+ this.fins = null;
+ // channel with null inputs
+ try {
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET).newDecoder(), -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString_internalBufferZero()
+ throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ // channel null
+ Reader testReader;
+ try {
+ testReader = Channels.newReader(null, Charset.forName(CODE_SET).newDecoder(), 0);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ assertEquals(0, readres);
+
+ this.fins = null;
+ // channel with null inputs
+ try {
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ testReader = Channels.newReader(rbChannel, Charset.forName(CODE_SET).newDecoder(), -1);
+ assertNotNull(testReader);
+ assertFalse(testReader.ready());
+ readres = testReader.read(charBuf);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newReader(ReadableByteChannel, String)'
+ */
+ public void testNewReaderReadableByteChannelString() throws IOException {
+ int bufSize = this.testNum;
+ int readres = 0;
+ CharBuffer charBuf = CharBuffer.allocate(bufSize);
+ this.fins = new FileInputStream(tmpFile);
+ ReadableByteChannel rbChannel = Channels.newChannel(this.fins);
+ Reader testReader = Channels.newReader(rbChannel, Charset.forName(
+ CODE_SET).newDecoder(), //$NON-NLS-1$
+ -1);
+ Reader testReader_s = Channels.newReader(rbChannel, CODE_SET); //$NON-NLS-1$
+
+ assertEquals(this.fileSize, this.fins.available());
+ // not ready...
+ assertFalse(testReader.ready());
+ assertFalse(testReader_s.ready());
+ // still reads
+ readres = testReader.read(charBuf);
+ assertEquals(bufSize, readres);
+ assertEquals(0, this.fins.available());
+
+ try {
+ readres = testReader.read((CharBuffer) null);
+ fail();
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ readres = testReader_s.read(charBuf);
+ assertEquals(0, readres);
+ assertTrue(testReader.ready());
+ assertFalse(testReader_s.ready());
+ }
+
+ /*
+ * Zero-Buffer
+ */
+ public void testNewWriterWritableByteChannelString_internalBufZero()
+ throws IOException {
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ // null channel
+ try {
+ Writer testWriter = Channels.newWriter(null, Charset.forName(CODE_SET).newEncoder(), -1);
+ } catch (NullPointerException expected) {
+ }
+
+ // channel with null input
+ this.fouts = null;
+ try {
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /*
+ * this test cannot be passed when buffer set to 0!
+ */
+ public void testNewWriterWritableByteChannelString_InputNull()
+ throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ Writer testWriter = Channels.newWriter(wbChannel, Charset.forName(
+ CODE_SET).newEncoder(), //$NON-NLS-1$
+ 1);
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ // can write to buffer
+ testWriter.write(writebuf);
+ testWriter.flush();
+ testWriter.close();
+
+ }
+
+ /*
+ * Test method for
+ * 'java.nio.channels.Channels.newWriter(WritableByteChannel, String)'
+ */
+ public void testNewWriterWritableByteChannelString() throws IOException {
+ this.fouts = new FileOutputStream(tmpFile);
+ WritableByteChannel wbChannel = Channels.newChannel(this.fouts);
+ Writer testWriter = Channels.newWriter(wbChannel, CODE_SET); //$NON-NLS-1$
+ Writer testWriter_s = Channels.newWriter(wbChannel, Charset.forName(
+ CODE_SET).newEncoder(), //$NON-NLS-1$
+ -1);
+
+ String writebuf = ""; //$NON-NLS-1$
+ for (int val = 0; val < this.writebufSize / 2; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ byte[] bit = new byte[1];
+ bit[0] = 80;
+ this.fouts.write(bit);
+ this.assertFileSizeSame(tmpFile, 1);
+
+ // writer continues to write after '1',what the fouts write
+ testWriter.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ // testwriter_s does not know if testwrite writes
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ // testwriter_s even does not know if himself writes?
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+
+ // close the fouts, no longer writable for testWriter
+ for (int val = 0; val < this.writebufSize; val++) {
+ writebuf = writebuf + ((char) (val + 64));
+ }
+ this.fouts.close();
+ testWriter_s.write(writebuf);
+ testWriter.flush();
+ this.assertFileSizeSame(tmpFile, this.writebufSize / 2 + 1);
+ }
+
+ /**
+ * @tests java.nio.channels.Channels#newReader(ReadableByteChannel channel,
+ * String charsetName)
+ */
+ public void test_newReader_LReadableByteChannel_LString()
+ throws IOException {
+ InetSocketAddress localAddr = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr);
+
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr);
+ sc.configureBlocking(false);
+ assertFalse(sc.isBlocking());
+
+ ssc.accept().close();
+ ssc.close();
+ assertFalse(sc.isBlocking());
+
+ Reader reader = Channels.newReader(sc, "UTF16");
+ try {
+ int i = reader.read();
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException expected) {
+ }
+
+ try {
+ Channels.newInputStream(sc).read();
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException expected) {
+ }
+
+ sc.close();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
new file mode 100644
index 0000000..aba37ec
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedByInterruptExceptionTest.java
@@ -0,0 +1,53 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.ClosedByInterruptException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedByInterruptException
+ */
+public class ClosedByInterruptExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.ClosedByInterruptException#ClosedByInterruptException()}
+ */
+ public void test_Constructor() {
+ ClosedByInterruptException e = new ClosedByInterruptException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedByInterruptException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedByInterruptException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
new file mode 100644
index 0000000..3ba322f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.ClosedChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedChannelException
+ */
+public class ClosedChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.ClosedChannelException#ClosedChannelException()}
+ */
+ public void test_Constructor() {
+ ClosedChannelException e = new ClosedChannelException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedChannelException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
new file mode 100644
index 0000000..745d697
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ClosedSelectorExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.ClosedSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ClosedSelectorException
+ */
+public class ClosedSelectorExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.ClosedSelectorException#ClosedSelectorException()}
+ */
+ public void test_Constructor() {
+ ClosedSelectorException e = new ClosedSelectorException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ClosedSelectorException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ClosedSelectorException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..0e909ba
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ConnectionPendingExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.ConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for ConnectionPendingException
+ */
+public class ConnectionPendingExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.ConnectionPendingException#ConnectionPendingException()}
+ */
+ public void test_Constructor() {
+ ConnectionPendingException e = new ConnectionPendingException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new ConnectionPendingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new ConnectionPendingException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
new file mode 100644
index 0000000..cff718e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/DatagramChannelTest.java
@@ -0,0 +1,2557 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Test for DatagramChannel
+ *
+ */
+public class DatagramChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private static final int CAPACITY_1KB = 1024;
+
+ private static final int CAPACITY_64KB = 65536;
+
+ private static final int CAPACITY_ZERO = 0;
+
+ private static final int CAPACITY_ONE = 1;
+
+ private static final int TIME_UNIT = 500;
+
+ private InetSocketAddress localAddr1;
+
+ private InetSocketAddress localAddr2;
+
+ private DatagramChannel channel1;
+
+ private DatagramChannel channel2;
+
+ private DatagramSocket datagramSocket1;
+
+ private DatagramSocket datagramSocket2;
+
+ // The port to be used in test cases.
+ private int testPort;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.channel1 = DatagramChannel.open();
+ this.channel2 = DatagramChannel.open();
+ int[] ports = Support_PortManager.getNextPortsForUDP(5);
+ this.localAddr1 = new InetSocketAddress("127.0.0.1", ports[0]);
+ this.localAddr2 = new InetSocketAddress("127.0.0.1", ports[1]);
+ this.datagramSocket1 = new DatagramSocket(ports[2]);
+ this.datagramSocket2 = new DatagramSocket(ports[3]);
+ testPort = ports[4];
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.channel1) {
+ try {
+ this.channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.channel2) {
+ try {
+ this.channel2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.datagramSocket1) {
+ try {
+ this.datagramSocket1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.datagramSocket2) {
+ try {
+ this.datagramSocket2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ localAddr1 = null;
+ localAddr2 = null;
+ super.tearDown();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int val = this.channel1.validOps();
+ assertEquals(5, val);
+ assertEquals(val, testMock.validOps());
+ assertEquals(val, testMocknull.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.open()'
+ */
+ public void testOpen() {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ assertNull(testMocknull.provider());
+ assertNotNull(testMock.provider());
+ assertEquals(this.channel1.provider(), testMock.provider());
+ assertEquals(5, testMock.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+ */
+ public void testReadByteBufferArray() throws IOException {
+ final int testNum = 0;
+ long readres = testNum;
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int bufSize = 10;
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ readres = testMock.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ readBuf = new ByteBuffer[bufSize];
+ try {
+ readres = this.channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ readres = testMock.read(readBuf);
+ assertEquals(testNum, readres);
+ readres = testMocknull.read(readBuf);
+ assertEquals(testNum, readres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.read(ByteBuffer)'
+ */
+ public void testReadByteBufferArray_BufNull() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMocknull.read(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ int bufSize = 10;
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ readBuf = new ByteBuffer[bufSize];
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ long writeres = 0;
+ writeres = testMock.write(readBuf);
+
+ assertEquals(0, writeres);
+ writeres = testMocknull.write(readBuf);
+ assertEquals(0, writeres);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.DatagramChannel.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer_Bufnull() throws IOException {
+ MockDatagramChannel testMock = new MockDatagramChannel(SelectorProvider
+ .provider());
+ MockDatagramChannel testMocknull = new MockDatagramChannel(null);
+ ByteBuffer[] readBuf = null;
+ try {
+ this.channel1.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMock.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMocknull.write(readBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for socket()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws SocketException
+ */
+ public void testSocket_BasicStatusBeforeConnect() throws SocketException {
+ assertFalse(this.channel1.isConnected());// not connected
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketBeforeConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+ this.channel1.connect(localAddr1);
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_BasicStatusAfterConnect()
+ throws IOException {
+ this.channel1.connect(localAddr1);
+ this.channel1.configureBlocking(false);
+ DatagramSocket s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1);
+ DatagramSocket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_ActionsBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionBeforeConnect(s);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.socket()'
+ *
+ * @throws IOException
+ */
+ public void testSocket_Block_ActionsAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.connect(localAddr1);
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionAfterConnect(s);
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnect() throws IOException {
+ this.channel1.connect(localAddr1);
+ this.channel1.configureBlocking(false);
+ DatagramSocket s = this.channel1.socket();
+ assertSocketActionAfterConnect(s);
+ }
+
+ private void assertSocketBeforeConnect(DatagramSocket s)
+ throws SocketException {
+ assertFalse(s.isBound());
+ assertFalse(s.isClosed());
+ assertFalse(s.isConnected());
+ assertFalse(s.getBroadcast());
+ assertFalse(s.getReuseAddress());
+ assertNull(s.getInetAddress());
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
+ assertEquals(s.getLocalPort(), 0);
+ assertNull(s.getLocalSocketAddress());
+ assertEquals(s.getPort(), -1);
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ assertNull(s.getRemoteSocketAddress());
+ assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+ }
+
+ private void assertSocketAfterConnect(DatagramSocket s)
+ throws SocketException {
+ assertTrue(s.isBound());
+ assertFalse(s.isClosed());
+ assertTrue(s.isConnected());
+ assertFalse(s.getBroadcast());
+ assertFalse(s.getReuseAddress());
+ assertSame(s.getInetAddress(), localAddr1.getAddress());
+ assertEquals(s.getLocalAddress(), localAddr1.getAddress());
+ assertNotNull(s.getLocalSocketAddress());
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ // not same , but equals
+ assertNotSame(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+ assertEquals(s.getRemoteSocketAddress(), (SocketAddress) localAddr1);
+ assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(s.getSoTimeout(), 0);
+ assertEquals(s.getTrafficClass(), 0);
+ }
+
+ private void assertSocketActionBeforeConnect(DatagramSocket s)
+ throws IOException {
+ s.connect(localAddr2);
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.disconnect();
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketActionAfterConnect(DatagramSocket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ s.connect(localAddr2);
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+ // not changed
+ assertEquals(s.getPort(), localAddr1.getPort());
+
+ s.disconnect();
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for configureBlocking()
+ // -------------------------------------------------------------------
+
+ public void testConfigureBlocking_Read() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_1KB);
+ new Thread() {
+ public void run() {
+ try {
+ sleep(TIME_UNIT * 5);
+ channel1.configureBlocking(false);
+ assertFalse(channel1.isBlocking());
+ datagramSocket1.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ SocketAddress addr = channel1.receive(buf);
+ assertNull(addr);
+ }
+
+ // -------------------------------------------------------------------
+ // Test for isConnected()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.isConnected()'
+ *
+ * @throws IOException
+ */
+ public void testIsConnected_WithServer() throws IOException {
+ connectLocalServer();
+ disconnectAfterConnected();
+ this.datagramSocket1.close();
+ this.channel1.close();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for connect()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ */
+ public void testConnect_BlockWithServer() throws IOException {
+ // blocking mode
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ datagramSocket1.close();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ */
+ public void testConnect_BlockNoServer() throws IOException {
+ connectWithoutServer();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_NonBlockWithServer() throws IOException {
+ // Non blocking mode
+ this.channel1.configureBlocking(false);
+ connectLocalServer();
+ datagramSocket1.close();
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_Null() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ try {
+ this.channel1.connect(null);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_UnsupportedType() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ class SubSocketAddress extends SocketAddress {
+ private static final long serialVersionUID = 1L;
+
+ public SubSocketAddress() {
+ super();
+ }
+ }
+ SocketAddress newTypeAddress = new SubSocketAddress();
+ try {
+ this.channel1.connect(newTypeAddress);
+ fail("Should throw an UnsupportedAddressTypeException here.");
+ } catch (UnsupportedAddressTypeException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ */
+ public void testConnect_Unresolved() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ InetSocketAddress unresolved = new InetSocketAddress(
+ "unresolved address", 1080);
+ try {
+ this.channel1.connect(unresolved);
+ fail("Should throw an UnresolvedAddressException here."); //$NON-NLS-1$
+ } catch (UnresolvedAddressException e) {
+ // OK.
+ }
+ }
+
+ public void testConnect_EmptyHost() throws Exception {
+ assertFalse(this.channel1.isConnected());
+
+ assertEquals(this.channel1, this.channel1
+ .connect(new InetSocketAddress("", 1081))); //$NON-NLS-1$
+
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_ClosedChannelException() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_IllegalStateException() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ // connect after connected.
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw IllegalStateException."); //$NON-NLS-1$
+ } catch (IllegalStateException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.connect(SocketAddress)'
+ *
+ * @throws IOException
+ *
+ */
+ public void testConnect_CheckOpenBeforeStatus() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ // connect after connected.
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ // checking open is before checking status.
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ private void disconnectAfterConnected() throws IOException {
+ assertTrue(this.channel1.isConnected());
+ this.channel1.disconnect();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ private void disconnectAfterClosed() throws IOException {
+ assertFalse(this.channel1.isOpen());
+ assertFalse(this.channel1.isConnected());
+ this.channel1.disconnect();
+ assertFalse(this.channel1.isConnected());
+ }
+
+ private void connectLocalServer() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.datagramSocket1.isBound());
+ assertSame(this.channel1, this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ }
+
+ private void connectWithoutServer() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.datagramSocket1.close();
+ assertTrue(this.datagramSocket1.isClosed());
+ assertSame(this.channel1, this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for disconnect()
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ assertEquals(this.channel1, this.channel1.disconnect());
+ assertFalse(this.channel1.isConnected());
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_UnconnectedClosed() throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ assertEquals(this.channel1, this.channel1.disconnect());
+ assertFalse(this.channel1.isConnected());
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BlockWithServerChannelClosed()
+ throws IOException {
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after channel close
+ this.channel1.close();
+ disconnectAfterClosed();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_NonBlockWithServerChannelClosed()
+ throws IOException {
+ this.channel1.configureBlocking(false);
+ connectLocalServer();
+ // disconnect after channel close
+ this.channel1.close();
+ disconnectAfterClosed();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_BlockWithServerServerClosed() throws IOException {
+ assertTrue(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after server close
+ this.datagramSocket1.close();
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isConnected());
+ disconnectAfterConnected();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.disconnect()'
+ *
+ * @throws IOException
+ */
+ public void testDisconnect_NonBlockWithServerServerClosed()
+ throws IOException {
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.isBlocking());
+ connectLocalServer();
+ // disconnect after server close
+ this.datagramSocket1.close();
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isConnected());
+ disconnectAfterConnected();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for receive(): Behavior Without Server.
+ // -------------------------------------------------------------------
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedNull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedReadonly() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufZero() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ZERO);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufNotEmpty() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ // buf is not empty
+ dst.put((byte) 88);
+ assertEquals(dst.position() + CAPACITY_NORMAL - 1, dst.limit());
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedBufFull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+ // buf is full
+ dst.put((byte) 88);
+ assertEquals(dst.position(), dst.limit());
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedClose() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ assertNull(this.channel1.receive(dst));
+ fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedCloseNull() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ // checking buffer before checking open
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_UnconnectedCloseReadonly() throws Exception {
+ assertFalse(this.channel1.isConnected());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNonBlockNoServer(CAPACITY_NORMAL);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerNull() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerNull() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerReadonly() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerReadonly() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufZero() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNonBlockNoServer(CAPACITY_ZERO);
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufNotEmpty() throws Exception {
+ this.channel1.configureBlocking(false);
+ connectWithoutServer();
+ ByteBuffer dst = allocateNonEmptyBuf();
+ assertNull(this.channel1.receive(dst));
+ }
+
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerBufFull() throws Exception {
+ this.channel1.configureBlocking(false);
+ connectWithoutServer();
+ ByteBuffer dst = allocateFullBuf();
+ assertNull(this.channel1.receive(dst));
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerChannelClose() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelClose();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerChannelClose() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelClose();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerCloseNull() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelCloseNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerCloseNull() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelCloseNull();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_NonBlockNoServerCloseReadonly() throws Exception {
+ this.channel1.configureBlocking(false);
+ receiveNoServerChannelCloseReadonly();
+ }
+
+ /**
+ * Test method for 'DatagramChannelImpl.receive(ByteBuffer)'
+ *
+ * @throws Exception
+ */
+ public void testReceive_BlockNoServerCloseReadonly() throws Exception {
+ assertTrue(this.channel1.isBlocking());
+ receiveNoServerChannelCloseReadonly();
+ }
+
+ private void receiveNoServerNull() throws IOException {
+ connectWithoutServer();
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerReadonly() throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNonBlockNoServer(int size) throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(size);
+ assertNull(this.channel1.receive(dst));
+ }
+
+ private void receiveNoServerChannelClose() throws IOException {
+ connectWithoutServer();
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ assertNull(this.channel1.receive(dst));
+ fail("Should throw a ClosedChannelException here."); //$NON-NLS-1$
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerChannelCloseNull() throws IOException {
+ connectWithoutServer();
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ try {
+ this.channel1.receive(null);
+ fail("Should throw a NPE here."); //$NON-NLS-1$
+ } catch (NullPointerException e) {
+ // OK.
+ }
+ }
+
+ private void receiveNoServerChannelCloseReadonly() throws IOException {
+ connectWithoutServer();
+ this.channel1.close();
+ assertFalse(this.channel1.isOpen());
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL)
+ .asReadOnlyBuffer();
+ assertTrue(dst.isReadOnly());
+ try {
+ this.channel1.receive(dst);
+ fail("Should throw an IllegalArgumentException here."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ private ByteBuffer allocateFullBuf() {
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_ONE);
+ // buf is full
+ dst.put((byte) 88);
+ assertEquals(dst.position(), dst.limit());
+ return dst;
+ }
+
+ private ByteBuffer allocateNonEmptyBuf() {
+ ByteBuffer dst = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ // buf is not empty
+ dst.put((byte) 88);
+ dst.put((byte) 99);
+ assertEquals(dst.position() + CAPACITY_NORMAL - 2, dst.limit());
+ return dst;
+ }
+
+ // -------------------------------------------------------------------
+ // Test for send(): Behavior without server.
+ // -------------------------------------------------------------------
+
+ private void sendDataBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+ throws IOException {
+ InetSocketAddress ipAddr = addr;
+ assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+ assertTrue(this.channel1.isOpen());
+ assertTrue(this.channel1.isBlocking());
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ }
+
+ private void sendDataNonBlocking(InetSocketAddress addr, ByteBuffer writeBuf)
+ throws IOException {
+ InetSocketAddress ipAddr = addr;
+ this.channel1.configureBlocking(false);
+ assertEquals(CAPACITY_NORMAL, this.channel1.send(writeBuf, ipAddr));
+ assertTrue(this.channel1.isOpen());
+ assertFalse(this.channel1.isBlocking());
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.send(ByteBuffer, SocketAddress)'
+ */
+ public void testSend_NoServerBlockingCommon() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataBlocking(localAddr1, writeBuf);
+ }
+
+ public void testSend_NoServerNonblockingCommon() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataNonBlocking(localAddr1, writeBuf);
+ }
+
+ public void testSend_NoServerTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataBlocking(localAddr1, writeBuf);
+ // can not buffer twice!
+ assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+ try {
+ channel1.send(writeBuf, localAddr2);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerNonBlockingTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ sendDataNonBlocking(localAddr1, writeBuf);
+ // can not buffer twice!
+ assertEquals(0, this.channel1.send(writeBuf, localAddr1));
+ try {
+ channel1.send(writeBuf, localAddr2);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerBufNull() throws IOException {
+ try {
+ sendDataBlocking(localAddr1, null);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerBufNullTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(localAddr1, null);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ sendDataBlocking(localAddr1, writeBuf);
+ try {
+ channel1.send(null, localAddr2);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerAddrNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(null, writeBuf);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSend_NoServerAddrNullTwice() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ sendDataBlocking(null, writeBuf);
+ fail("Should throw a NPE here.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ sendDataBlocking(localAddr1, writeBuf);
+ try {
+ channel1.send(writeBuf, null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for receive()and send(): Send and Receive with Real Data
+ // -------------------------------------------------------------------
+
+ public void testReceiveSend_Block_Normal() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2,
+ "some normal string in testReceiveSend_Normal");
+ }
+
+ public void testReceiveSend_Block_NotBound() throws Exception {
+ // not bound
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertNull(channel1.receive(buf));
+ assertFalse(channel1.socket().isBound());
+ }
+
+ public void testReceiveSend_NonBlock_NotBound() throws Exception {
+ // not bound
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ sendByChannel("some normal string in testReceiveSend_Normal",
+ localAddr2);
+ ByteBuffer buf = ByteBuffer.wrap(new byte[CAPACITY_NORMAL]);
+ assertNull((InetSocketAddress) this.channel1.receive(buf));
+ }
+
+ public void testReceiveSend_Block_Normal_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket(
+ "some normal string in testReceiveSend_Normal_S2C", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2,
+ "some normal string in testReceiveSend_Normal_S2C");
+ }
+
+ public void testReceiveSend_Block_Normal_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ String str1 = "some normal string in testReceiveSend_Normal_C2S";
+ sendByChannel(str1, localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+ }
+
+ public void testReceiveSend_NonBlock_Normal_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ String str1 = "some normal string in testReceiveSend_Normal_C2S";
+ sendByChannel(str1, localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, str1);
+ }
+
+ public void testReceiveSend_Normal_S2S() throws Exception {
+ String msg = "normal string in testReceiveSend_Normal_S2S";
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+ localAddr2);
+ datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+ this.datagramSocket1.send(rdp);
+ byte[] buf = new byte[CAPACITY_NORMAL];
+ this.datagramSocket2.setSoTimeout(TIME_UNIT);
+ rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket2.receive(rdp);
+ assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+ }
+
+ public void testReceiveSend_Block_Empty() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Block_Empty_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty_S2C() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("", localAddr2);
+ receiveByChannel(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Block_Empty_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("", localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_NonBlock_Empty_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("", localAddr2);
+ receiveByDatagramSocket(CAPACITY_NORMAL, localAddr2, "");
+ }
+
+ public void testReceiveSend_Empty_S2S() throws Exception {
+ String msg = "";
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(msg.getBytes(), msg.length(),
+ localAddr2);
+ datagramSocket2 = new DatagramSocket(localAddr2.getPort());
+ this.datagramSocket1.send(rdp);
+ byte[] buf = new byte[CAPACITY_NORMAL];
+ this.datagramSocket2.setSoTimeout(TIME_UNIT);
+ rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket2.receive(rdp);
+ assertEquals(new String(buf, 0, CAPACITY_NORMAL).trim(), msg);
+ }
+
+ public void testReceiveSend_Block_Oversize() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel("0123456789", localAddr2);
+ receiveByChannel(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_Block_Oversize_C2S() throws Exception {
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("0123456789", localAddr2);
+ receiveByDatagramSocket(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_NonBlock_Oversize_C2S() throws Exception {
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+ this.datagramSocket1 = new DatagramSocket(localAddr2.getPort());
+ sendByChannel("0123456789", localAddr2);
+ receiveByDatagramSocket(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_Block_Oversize_S2C() throws Exception {
+ this.channel1.socket().bind(localAddr2);
+ sendByDatagramSocket("0123456789", localAddr2);
+ receiveByChannel(5, localAddr2, "01234");
+ }
+
+ public void testReceiveSend_8K() throws Exception {
+ StringBuffer str8k = new StringBuffer();
+ for (int i = 0; i < 8 * CAPACITY_1KB; i++) {
+ str8k.append('a');
+ }
+ String str = str8k.toString();
+ this.channel1.socket().bind(localAddr2);
+ sendByChannel(str, localAddr2);
+ receiveByChannel(8 * CAPACITY_1KB, localAddr2, str);
+ }
+
+ public void testReceiveSend_64K() throws Exception {
+ StringBuffer str64k = new StringBuffer();
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ str64k.append('a');
+ }
+ String str = str64k.toString();
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.send(ByteBuffer.wrap(str.getBytes()), localAddr1);
+ fail("Should throw SocketException!");
+ } catch (SocketException e) {
+ //expected
+ }
+ }
+
+ private void sendByChannel(String data, InetSocketAddress address)
+ throws Exception {
+ try {
+ assertEquals(data.length(), this.channel2.send(ByteBuffer.wrap(data
+ .getBytes()), address));
+ } finally {
+ this.channel2.close();
+ }
+ }
+
+ private void sendByDatagramSocket(String data, InetSocketAddress address)
+ throws Exception {
+ this.datagramSocket1 = new DatagramSocket(testPort);
+ DatagramPacket rdp = new DatagramPacket(data.getBytes(), data.length(),
+ address);
+ this.datagramSocket1.send(rdp);
+ }
+
+ private void receiveByChannel(int bufSize, InetSocketAddress address,
+ String expectedString) throws IOException {
+ try {
+ ByteBuffer buf = ByteBuffer.wrap(new byte[bufSize]);
+ InetSocketAddress returnAddr = null;
+ long startTime = System.currentTimeMillis();
+ do {
+ returnAddr = (InetSocketAddress) this.channel1.receive(buf);
+ // continue loop when channel1 is non-blocking and no data was
+ // received.
+ if (channel1.isBlocking() || null != returnAddr) {
+ break;
+ }
+ // avoid dead loop
+ assertTimeout(startTime, 10000);
+ } while (true);
+ int length = returnAddr.getAddress().getAddress().length;
+ for (int i = 0; i < length; i++) {
+ assertEquals(returnAddr.getAddress().getAddress()[i],
+ InetAddress.getByName("127.0.0.1").getAddress()[i]);
+ }
+ // port is NOT equal
+ assertFalse(returnAddr.getPort() == address.getPort());
+ assertEquals(new String(buf.array(), 0, bufSize).trim(),
+ expectedString);
+ } finally {
+ this.channel1.close();
+ }
+ }
+
+ /*
+ * Fails if the difference between current time and start time is greater
+ * than timeout.
+ */
+ private void assertTimeout(long startTime, long timeout) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - startTime) > timeout) {
+ fail("Timeout");
+ }
+ }
+
+ private void receiveByDatagramSocket(int bufSize,
+ InetSocketAddress address, String expectedString)
+ throws IOException {
+ byte[] buf = new byte[bufSize];
+ this.datagramSocket1.setSoTimeout(6000);
+ DatagramPacket rdp = new DatagramPacket(buf, buf.length);
+ this.datagramSocket1.receive(rdp);
+ assertEquals(new String(buf, 0, bufSize).trim(), expectedString);
+ }
+
+ public void testRead_NoSecurity() throws Exception {
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ String strHello = "hello";
+ localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+ this.channel1.socket().bind(localAddr1);
+ this.channel2.socket().bind(localAddr2);
+ this.channel1.connect(localAddr2);
+ this.channel2.send(ByteBuffer.wrap(strHello.getBytes()), localAddr1);
+ assertEquals(strHello.length(), this.channel1.read(buf));
+ assertAscii(buf, strHello);
+ }
+
+ public void testReceive_Peek_NoSecurity_Nonblocking() throws Exception {
+ String strHello = "hello";
+ localAddr1 = new InetSocketAddress("127.0.0.1", testPort);
+ this.channel1.socket().bind(localAddr1);
+ sendByChannel(strHello, localAddr1);
+ this.channel1.configureBlocking(false);
+ // for accepted addr, no problem.
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ InetSocketAddress source = (InetSocketAddress) this.channel1.receive(buf);
+ assertEquals(localAddr1.getAddress(), source.getAddress());
+ assertAscii(buf, strHello);
+ }
+
+ private static void assertAscii(ByteBuffer b, String s) {
+ assertEquals(s.length(), b.position());
+ for (int i = 0; i < s.length(); ++i) {
+ assertEquals(s.charAt(i), b.get(i));
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for write()
+ // -------------------------------------------------------------------
+
+ private void connectWriteBuf(InetSocketAddress ipAddr, ByteBuffer buf)
+ throws IOException {
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(buf));
+ assertEquals(0, this.channel1.write(buf));
+ }
+
+ private void noconnectWrite(ByteBuffer buf) throws IOException {
+ try {
+ this.channel1.write(buf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.write(ByteBuffer)'
+ */
+ public void testWriteByteBuffer_Block() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ connectWriteBuf(localAddr1, writeBuf);
+ }
+
+ public void testWriteByteBuffer_NonBlock() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(false);
+ connectWriteBuf(localAddr1, writeBuf);
+ }
+
+ public void testWriteByteBuffer_Block_closed() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ noconnectWrite(writeBuf);
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_NonBlock_closed() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ // non block mode
+ this.channel1.configureBlocking(false);
+ noconnectWrite(writeBuf);
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_Block_BufNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf));
+ datagramSocket1.close();
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_NonBlock_BufNull() throws IOException {
+ ByteBuffer writeBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+
+ // non block mode
+ this.channel1.configureBlocking(false);
+
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf));
+ datagramSocket1.close();
+ try {
+ this.channel1.write((ByteBuffer) null);
+ fail("Should throw NPE.");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt_Block() throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw NotYetConnectedException.");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+ }
+
+ public void testWriteByteBufferArrayIntInt_NonBlock() throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ // non-block mode
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw NotYetConnectedException.");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+
+ }
+
+ public void testWriteByteBufferArrayIntInt_NoConnectIndexBad()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.write(writeBuf, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ // cannot be buffered again!
+ assertEquals(0, this.channel1.write(writeBuf, 0, 1));
+ }
+
+ public void testWriteByteBufferArrayIntInt_ConnectedIndexBad()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write(writeBuf, -1, 2);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNullNoConnect()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ this.channel1.write(null, 0, 2);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ this.channel1.write(writeBuf, -1, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.write(writeBuf, 0, 3);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNullConnect()
+ throws IOException {
+ ByteBuffer[] writeBuf = new ByteBuffer[2];
+ writeBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ this.channel1.write(null, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ datagramSocket1.close();
+ try {
+ this.channel1.write(null, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for read()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'DatagramChannelImpl.read(ByteBuffer)'
+ */
+ public void testReadByteBuffer() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ try {
+ this.channel1.read(readBuf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf));
+ this.channel1.close();
+ try {
+ this.channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ public void testReadByteBuffer_bufNull() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocateDirect(0);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(readBuf);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ try {
+ channel1.read((ByteBuffer) null);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf));
+ datagramSocket1.close();
+ }
+
+ /*
+ * Test method for 'DatagramChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt() throws IOException {
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(readBuf, 0, 2);
+ fail("should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ datagramSocket1.close();
+ }
+
+ public void testReadByteBufferArrayIntInt_exceptions() throws IOException {
+ //regression test for HARMONY-932
+ try {
+ DatagramChannel.open().read(new ByteBuffer[] {}, 2, Integer.MAX_VALUE);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ DatagramChannel.open().read(new ByteBuffer[] {}, -1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ DatagramChannel.open().read((ByteBuffer[]) null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void testReadByteBufferArrayIntInt_BufNull() throws IOException {
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ InetSocketAddress ipAddr = localAddr1;
+ try {
+ this.channel1.read(null, 0, 0);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(ipAddr);
+ assertTrue(this.channel1.isConnected());
+ this.channel1.configureBlocking(false);
+ // note : blocking-mode will make the read process endless!
+ try {
+ this.channel1.read(null, 0, 0);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ try {
+ this.channel1.read(readBuf, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.read(readBuf, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ datagramSocket1.close();
+ }
+
+ // -------------------------------------------------------------------
+ // test read and write
+ // -------------------------------------------------------------------
+
+ public void testReadWrite_configureBlock() throws Exception {
+ byte[] targetArray = new byte[2];
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel1.configureBlocking(false);
+ channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }.start();
+ try {
+ this.channel1.read(targetBuf);
+ fail("should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // ok
+ }
+ }
+
+ public void testReadWrite_Block_Zero() throws Exception {
+ byte[] sourceArray = new byte[0];
+ byte[] targetArray = new byte[0];
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ int readCount = this.channel2.read(targetBuf);
+
+ assertEquals(0, readCount);
+ }
+
+ public void testReadWrite_Block_Normal() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, CAPACITY_NORMAL, "testReadWrite_Block_Normal");
+ }
+
+ public void testReadWrite_Block_Empty() throws Exception {
+ // empty buf
+ byte[] sourceArray = "".getBytes();
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // empty message let the reader blocked
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_changeBlock_Empty() throws Exception {
+ // empty buf
+ byte[] sourceArray = "".getBytes();
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(0, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // empty message let the reader blocked
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.configureBlocking(false);
+ Thread.sleep(TIME_UNIT * 5);
+ channel2.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ try {
+ assertTrue(this.channel2.isBlocking());
+ this.channel2.read(targetBuf);
+ fail("Should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ assertFalse(this.channel2.isBlocking());
+ // OK.
+ }
+ }
+
+ public void testReadWrite_Block_8KB() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+ byte[] targetArray = new byte[CAPACITY_1KB * 8];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, 8 * CAPACITY_1KB, "testReadWrite_Block_8KB");
+ }
+
+ /*
+ * sender write the sourceArray whose size is dataSize, and receiver read
+ * the data into targetArray
+ */
+ private void readWriteReadData(DatagramChannel sender, byte[] sourceArray,
+ DatagramChannel receiver, byte[] targetArray, int dataSize,
+ String methodName) throws IOException {
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(dataSize, sender.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while (total < dataSize && (count = receiver.read(targetBuf)) != -1) {
+ total = total + count;
+ // 3s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 3000){
+ break;
+ }
+ }
+
+ assertEquals(dataSize, total);
+ assertEquals(targetBuf.position(), total);
+ targetBuf.flip();
+ targetArray = targetBuf.array();
+ for (int i = 0; i < targetArray.length; i++) {
+ assertEquals(targetArray[i], (byte) i);
+ }
+ }
+
+ public void testReadWrite_Block_64K() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_64KB];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ try {
+ channel1.write(sourceBuf);
+ fail("Should throw IOException");
+ } catch (IOException e) {
+ // too big
+ }
+ }
+
+ public void testReadWrite_Block_DifferentAddr() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr1);// the different addr
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ // the wrong connected addr will make the read blocked.
+ // we close the blocked channel
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_Block_WriterNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ closeBlockedReaderChannel2(targetBuf);
+ }
+
+ public void testReadWrite_Block_WriterBindLater() throws Exception {
+
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+
+ // bind and connect
+ // writer channel1 is bound later
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ // bind later
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ // write later
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, channel1.write(sourceBuf));
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while (total < CAPACITY_NORMAL && (count = channel2.read(targetBuf)) != -1) {
+ total = total + count;
+ // 3s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 3000){
+ break;
+ }
+ }
+
+ assertEquals(CAPACITY_NORMAL, total);
+ assertEquals(targetBuf.position(), total);
+ targetBuf.flip();
+ targetArray = targetBuf.array();
+ for (int i = 0; i < targetArray.length; i++) {
+ assertEquals(targetArray[i], (byte) i);
+ }
+
+ }
+
+ public void testReadWrite_Block_ReaderNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ // reader channel2 is not bound
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ closeBlockedReaderChannel2(targetBuf);
+
+ }
+
+ private void closeBlockedReaderChannel2(ByteBuffer targetBuf)
+ throws IOException {
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ channel2.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ }
+ }.start();
+ try {
+ assertTrue(this.channel2.isBlocking());
+ this.channel2.read(targetBuf);
+ fail("Should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // OK.
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test read and write in non-block mode.
+ // -------------------------------------------------------------------
+ public void testReadWrite_NonBlock_Normal() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, CAPACITY_NORMAL, "testReadWrite_NonBlock_Normal");
+ }
+
+ public void testReadWrite_NonBlock_8KB() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_1KB * 8];
+ byte[] targetArray = new byte[CAPACITY_1KB * 8];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ readWriteReadData(this.channel1, sourceArray, this.channel2,
+ targetArray, 8 * CAPACITY_1KB, "testReadWrite_NonBlock_8KB");
+ }
+
+ public void testReadWrite_NonBlock_DifferentAddr() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr1);// the different addr
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void testReadWrite_NonBlock_WriterNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.connect(localAddr1);
+ this.channel2.socket().bind(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void testReadWrite_NonBlock_ReaderNotBind() throws Exception {
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ byte[] targetArray = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < sourceArray.length; i++) {
+ sourceArray[i] = (byte) i;
+ }
+
+ this.channel1.configureBlocking(false);
+ this.channel2.configureBlocking(false);
+
+ // bind and connect
+ this.channel1.socket().bind(localAddr2);
+ this.channel1.connect(localAddr1);
+ this.channel2.connect(localAddr2);
+
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(sourceBuf));
+
+ // read
+ ByteBuffer targetBuf = ByteBuffer.wrap(targetArray);
+ assertEquals(0, this.channel2.read(targetBuf));
+ }
+
+ public void test_write_LBuffer_positioned() throws Exception {
+ // Regression test for Harmony-683
+ int position = 16;
+ DatagramChannel dc = DatagramChannel.open();
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ dc.connect(localAddr1);
+ // write
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ sourceBuf.position(position);
+ assertEquals(CAPACITY_NORMAL - position, dc.write(sourceBuf));
+ }
+
+ public void test_send_LBuffer_LSocketAddress_PositionNotZero()
+ throws Exception {
+ // regression test for Harmony-701
+ int CAPACITY_NORMAL = 256;
+ int position = 16;
+ DatagramChannel dc = DatagramChannel.open();
+ byte[] sourceArray = new byte[CAPACITY_NORMAL];
+ // send ByteBuffer whose position is not zero
+ ByteBuffer sourceBuf = ByteBuffer.wrap(sourceArray);
+ sourceBuf.position(position);
+ int ret = dc.send(sourceBuf, localAddr1);
+ // assert send (256 - 16) bytes
+ assertEquals(CAPACITY_NORMAL - position, ret);
+ // assert the position of ByteBuffer has been set
+ assertEquals(CAPACITY_NORMAL, sourceBuf.position());
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer[])
+ */
+ public void test_read_$LByteBuffer() throws Exception {
+ // regression test for Harmony-754
+ channel2.socket().bind(localAddr1);
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ channel2.connect(localAddr2);
+ channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+ channel1.configureBlocking(true);
+ assertEquals(CAPACITY_NORMAL, channel1.read(readBuf));
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read_$LByteBufferII() throws Exception {
+ // regression test for Harmony-754
+ channel2.socket().bind(localAddr1);
+ channel1.socket().bind(localAddr2);
+ channel1.connect(localAddr1);
+ channel2.connect(localAddr2);
+ channel2.write(ByteBuffer.allocate(CAPACITY_NORMAL));
+
+ ByteBuffer[] readBuf = new ByteBuffer[2];
+ readBuf[0] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+
+ channel1.configureBlocking(true);
+ assertEquals(CAPACITY_NORMAL, channel1.read(readBuf,0,2));
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_closed_nullBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = null;
+ DatagramChannel channel = DatagramChannel.open();
+ channel.close();
+ try{
+ channel.read(c);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_NotConnected_nullBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = null;
+ DatagramChannel channel = DatagramChannel.open();
+ try{
+ channel.read(c);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_readOnlyBuf() throws Exception {
+ // regression test for Harmony-754
+ ByteBuffer c = ByteBuffer.allocate(1);
+ DatagramChannel channel = DatagramChannel.open();
+ try{
+ channel.read(c.asReadOnlyBuffer());
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e){
+ } catch (IllegalArgumentException e){
+ // expected
+ }
+ channel.connect(localAddr1);
+ try{
+ channel.read(c.asReadOnlyBuffer());
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e){
+ // expected
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#send(ByteBuffer, SocketAddress)
+ */
+ public void test_send_LByteBuffer_LSocketAddress_closed() throws IOException{
+ // regression test for Harmony-913
+ channel1.close();
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ try {
+ channel1.send(buf, localAddr1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //pass
+ }
+ try {
+ channel1.send(null,localAddr1);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ //pass
+ }
+ try {
+ channel1.send(buf, null);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //pass
+ }
+ try {
+ channel1.send(null, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ //pass
+ }
+ }
+
+ /**
+ * @tests DatagramChannel#socket()
+ */
+ public void test_socket_IllegalBlockingModeException() throws Exception {
+ // regression test for Harmony-1036
+ DatagramChannel channel = DatagramChannel.open();
+ channel.configureBlocking(false);
+ DatagramSocket socket = channel.socket();
+ try {
+ socket.send(null);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ try {
+ socket.receive(null);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ public void test_bounded_harmony6493() throws IOException {
+ DatagramChannel server = DatagramChannel.open();
+ InetSocketAddress addr = new InetSocketAddress("localhost", 0);
+ server.socket().bind(addr);
+ SocketAddress boundedAddress = server.socket().getLocalSocketAddress();
+
+ DatagramChannel client = DatagramChannel.open();
+ ByteBuffer sent = ByteBuffer.allocate(1024);
+ sent.put("test".getBytes());
+ sent.flip();
+ client.send(sent, boundedAddress);
+ assertTrue(client.socket().isBound());
+
+ server.close();
+ client.close();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
new file mode 100644
index 0000000..cb34343
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelLockingTest.java
@@ -0,0 +1,208 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+/**
+ * API tests for the NIO FileChannel locking APIs
+ */
+public class FileChannelLockingTest extends TestCase {
+
+ private FileChannel readOnlyChannel;
+
+ private FileChannel writeOnlyChannel;
+
+ private FileChannel readWriteChannel;
+
+ private final String CONTENT = "The best things in life are nearest: Breath in your nostrils, light in your eyes, "
+ + "flowers at your feet, duties at your hand, the path of right just before you. Then do not grasp at the stars, "
+ + "but do life's plain, common work as it comes, certain that daily duties and daily bread are the sweetest "
+ + " things in life.--Robert Louis Stevenson";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // Create a three temporary files with content.
+ File[] tempFiles = new File[3];
+ for (int i = 0; i < tempFiles.length; i++) {
+ tempFiles[i] = File.createTempFile("testing", "tmp");
+ tempFiles[i].deleteOnExit();
+ FileWriter writer = new FileWriter(tempFiles[i]);
+ writer.write(CONTENT);
+ writer.close();
+ }
+
+ // Open read, write, and read/write channels on the temp files.
+ FileInputStream fileInputStream = new FileInputStream(tempFiles[0]);
+ readOnlyChannel = fileInputStream.getChannel();
+
+ FileOutputStream fileOutputStream = new FileOutputStream(tempFiles[1]);
+ writeOnlyChannel = fileOutputStream.getChannel();
+
+ RandomAccessFile randomAccessFile = new RandomAccessFile(tempFiles[2],
+ "rw");
+ readWriteChannel = randomAccessFile.getChannel();
+ }
+
+ protected void tearDown() throws IOException {
+ if (readOnlyChannel != null) {
+ readOnlyChannel.close();
+ }
+ if (writeOnlyChannel != null) {
+ writeOnlyChannel.close();
+ }
+ if (readWriteChannel != null) {
+ readWriteChannel.close();
+ }
+ }
+
+ public void test_illegalLocks() throws IOException {
+ // Cannot acquire an exclusive lock on a read-only file channel
+ try {
+ readOnlyChannel.lock();
+ fail("Acquiring a full exclusive lock on a read only channel should fail.");
+ } catch (NonWritableChannelException ex) {
+ // Expected.
+ }
+
+ // Cannot get a shared lock on a write-only file channel.
+ try {
+ writeOnlyChannel.lock(1, 10, true);
+ fail("Acquiring a shared lock on a write-only channel should fail.");
+ } catch (NonReadableChannelException ex) {
+ // expected
+ }
+ }
+
+ public void test_lockReadWrite() throws IOException {
+ // Acquire an exclusive lock across the entire file.
+ FileLock flock = readWriteChannel.lock();
+ if (flock != null) {
+ flock.release();
+ }
+ }
+
+ public void test_illegalLockParameters() throws IOException {
+ // Cannot lock negative positions
+ try {
+ readOnlyChannel.lock(-1, 10, true);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ writeOnlyChannel.lock(-1, 10, false);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ readWriteChannel.lock(-1, 10, false);
+ fail("Passing illegal args to lock should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // Lock a range at the front, shared.
+ FileLock flock1 = readWriteChannel.lock(22, 110, true);
+
+ // Try to acquire an overlapping lock.
+ try {
+ readWriteChannel.lock(75, 210, true);
+ } catch (OverlappingFileLockException exception) {
+ // expected
+ flock1.release();
+ }
+ }
+
+ public void test_lockLLZ() throws IOException {
+ // Lock a range at the front, non-shared.
+ FileLock flock1 = readWriteChannel.lock(0, 10, false);
+
+ // Lock a shared range further in the same file.
+ FileLock flock2 = readWriteChannel.lock(22, 100, true);
+
+ // The spec allows the impl to refuse shared locks
+ flock1.release();
+ flock2.release();
+ }
+
+ public void test_tryLock() throws IOException {
+ try {
+ readOnlyChannel.tryLock();
+ fail("Acquiring a full exclusive lock on a read channel should have thrown an exception.");
+ } catch (NonWritableChannelException ex) {
+ // Expected.
+ }
+ }
+
+ public void test_tryLockLLZ() throws IOException {
+ // It is illegal to request an exclusive lock on a read-only channel
+ try {
+ readOnlyChannel.tryLock(0, 99, false);
+ fail("Acquiring exclusive lock on read-only channel should fail");
+ } catch (NonWritableChannelException ex) {
+ // Expected
+ }
+
+ // It is invalid to request a lock starting before the file start
+ try {
+ readOnlyChannel.tryLock(-99, 0, true);
+ fail("Acquiring an illegal lock value should fail.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+
+ // Acquire a valid lock
+ FileLock tmpLock = readOnlyChannel.tryLock(0, 10, true);
+ assertTrue(tmpLock.isValid());
+ tmpLock.release();
+
+ // Acquire another valid lock -- and don't release it yet
+ FileLock lock = readOnlyChannel.tryLock(10, 788, true);
+ assertTrue(lock.isValid());
+
+ // Overlapping locks are illegal
+ try {
+ readOnlyChannel.tryLock(1, 23, true);
+ fail("Acquiring an overlapping lock should fail.");
+ } catch (OverlappingFileLockException ex) {
+ // Expected
+ }
+
+ // Adjacent locks are legal
+ FileLock adjacentLock = readOnlyChannel.tryLock(1, 3, true);
+ assertTrue(adjacentLock.isValid());
+ adjacentLock.release();
+
+ // Release longer lived lock
+ lock.release();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
new file mode 100644
index 0000000..9a89f7e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileChannelTest.java
@@ -0,0 +1,3121 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.MappedByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.NonReadableChannelException;
+import java.nio.channels.NonWritableChannelException;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.channels.Pipe;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.WritableByteChannel;
+import java.nio.channels.FileChannel.MapMode;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class FileChannelTest extends TestCase {
+
+ private static final int CAPACITY = 100;
+
+ private static final int LIMITED_CAPACITY = 2;
+
+ private static final int TIME_OUT = 10000;
+
+ private static final String CONTENT = "MYTESTSTRING needs to be a little long";
+
+ private static final byte[] TEST_BYTES;
+
+ private static final byte[] CONTENT_AS_BYTES;
+
+ private static final int CONTENT_AS_BYTES_LENGTH;
+
+ static {
+ try {
+ TEST_BYTES = "test".getBytes("iso8859-1");
+ CONTENT_AS_BYTES = CONTENT.getBytes("iso8859-1");
+ CONTENT_AS_BYTES_LENGTH = CONTENT_AS_BYTES.length;
+ } catch (UnsupportedEncodingException e) {
+ throw new Error(e);
+ }
+ }
+
+ private static final int CONTENT_LENGTH = CONTENT.length();
+
+ private FileChannel readOnlyFileChannel;
+
+ private FileChannel writeOnlyFileChannel;
+
+ private FileChannel readWriteFileChannel;
+
+ private File fileOfReadOnlyFileChannel;
+
+ private File fileOfWriteOnlyFileChannel;
+
+ private File fileOfReadWriteFileChannel;
+
+ private ReadableByteChannel readByteChannel;
+
+ private WritableByteChannel writableByteChannel;
+
+ private DatagramChannel datagramChannelSender;
+
+ private DatagramChannel datagramChannelReceiver;
+
+ private ServerSocketChannel serverSocketChannel;
+
+ private SocketChannel socketChannelSender;
+
+ private SocketChannel socketChannelReceiver;
+
+ private Pipe pipe;
+
+ // to read content from FileChannel
+ private FileInputStream fis;
+
+ private FileLock fileLock;
+
+ protected void setUp() throws Exception {
+ fileOfReadOnlyFileChannel = File.createTempFile(
+ "File_of_readOnlyFileChannel", "tmp");
+ fileOfReadOnlyFileChannel.deleteOnExit();
+ fileOfWriteOnlyFileChannel = File.createTempFile(
+ "File_of_writeOnlyFileChannel", "tmp");
+ fileOfWriteOnlyFileChannel.deleteOnExit();
+ fileOfReadWriteFileChannel = File.createTempFile(
+ "File_of_readWriteFileChannel", "tmp");
+ fileOfReadWriteFileChannel.deleteOnExit();
+ fis = null;
+ fileLock = null;
+ readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+ .getChannel();
+ writeOnlyFileChannel = new FileOutputStream(fileOfWriteOnlyFileChannel)
+ .getChannel();
+ readWriteFileChannel = new RandomAccessFile(fileOfReadWriteFileChannel,
+ "rw").getChannel();
+ }
+
+ protected void tearDown() {
+ if (null != readOnlyFileChannel) {
+ try {
+ readOnlyFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != writeOnlyFileChannel) {
+ try {
+ writeOnlyFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != readWriteFileChannel) {
+ try {
+ readWriteFileChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != fis) {
+ try {
+ fis.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ if (null != fileLock) {
+ try {
+ fileLock.release();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ if (null != fileOfReadOnlyFileChannel) {
+ fileOfReadOnlyFileChannel.delete();
+ }
+ if (null != fileOfWriteOnlyFileChannel) {
+ fileOfWriteOnlyFileChannel.delete();
+ }
+ if (null != fileOfReadWriteFileChannel) {
+ fileOfReadWriteFileChannel.delete();
+ }
+ if (null != datagramChannelSender) {
+ try {
+ datagramChannelSender.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != datagramChannelReceiver) {
+ try {
+ datagramChannelReceiver.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != serverSocketChannel) {
+ try {
+ serverSocketChannel.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != socketChannelSender) {
+ try {
+ socketChannelSender.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != socketChannelReceiver) {
+ try {
+ socketChannelReceiver.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != pipe) {
+ if (null != pipe.source()) {
+ try {
+ pipe.source().close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ if (null != pipe.sink()) {
+ try {
+ pipe.sink().close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeOnlyFileChannel.write(writeBuffer);
+ writeOnlyFileChannel.force(true);
+
+ byte[] readBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ fis.read(readBuffer);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, readBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ_closed() throws Exception {
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.force(true);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.force(false);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#force(boolean)
+ */
+ public void test_forceJ_ReadOnlyChannel() throws Exception {
+ // force on a read only file channel has no effect.
+ readOnlyFileChannel.force(true);
+ readOnlyFileChannel.force(false);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_Init() throws Exception {
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(0, writeOnlyFileChannel.position());
+ assertEquals(0, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ assertEquals(0, readOnlyFileChannel.position());
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH, readOnlyFileChannel.position());
+ }
+
+ /**
+ * Initializes test file.
+ *
+ * @param file
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void writeDataToFile(File file) throws FileNotFoundException,
+ IOException {
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ fos.write(CONTENT_AS_BYTES);
+ } finally {
+ fos.close();
+ }
+ }
+
+ /**
+ * Initializes large test file.
+ *
+ * @param file the file to be written
+ * @param size the content size to be written
+ * @throws FileNotFoundException
+ * @throws IOException
+ */
+ private void writeLargeDataToFile(File file, int size) throws FileNotFoundException,
+ IOException {
+ FileOutputStream fos = new FileOutputStream(file);
+ byte[] buf = new byte[size];
+
+ try {
+ // we don't care about content - just need a particular file size
+ fos.write(buf);
+ } finally {
+ fos.close();
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_WriteOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_LENGTH, writeOnlyFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_ReadWrite() throws Exception {
+ writeDataToFile(fileOfReadWriteFileChannel);
+
+ assertEquals(0, readWriteFileChannel.position());
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readWriteFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH, readWriteFileChannel.position());
+
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ readWriteFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_LENGTH * 2, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException expected) {
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException expected) {
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.position();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_Closed() throws Exception {
+ final long POSITION = 100;
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.position(POSITION);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.position(POSITION);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.position(POSITION);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_Negative() throws Exception {
+ final long NEGATIVE_POSITION = -1;
+ try {
+ readOnlyFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.position(NEGATIVE_POSITION);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // set the position of the read only file channel to POSITION
+ final int POSITION = 4;
+ readOnlyFileChannel.position(POSITION);
+
+ // reads the content left to readBuffer through read only file channel
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ int count = readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_LENGTH - POSITION, count);
+
+ // asserts the content read is the part which stays beyond the POSITION
+ readBuffer.flip();
+ int i = POSITION;
+ while (readBuffer.hasRemaining()) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ i++;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position(long)
+ */
+ public void test_positionJ_WriteOnly() throws Exception {
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // init data to write
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ // set the position of the write only file channel to POSITION
+ final int POSITION = 4;
+ writeOnlyFileChannel.position(POSITION);
+
+ // writes to the write only file channel
+ writeOnlyFileChannel.write(writeBuffer);
+ // force to write out.
+ writeOnlyFileChannel.close();
+
+ // gets the result of the write only file channel
+ byte[] result = new byte[POSITION + CONTENT_LENGTH];
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ fis.read(result);
+
+ // constructs the expected result which has content[0... POSITION] plus
+ // content[0...length()]
+ byte[] expectedResult = new byte[POSITION + CONTENT_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+ CONTENT_LENGTH);
+
+ // asserts result of the write only file channel same as expected
+ assertTrue(Arrays.equals(expectedResult, result));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size_Init() throws Exception {
+ assertEquals(0, readOnlyFileChannel.size());
+ assertEquals(0, writeOnlyFileChannel.size());
+ assertEquals(0, readWriteFileChannel.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ assertEquals(fileOfReadOnlyFileChannel.length(), readOnlyFileChannel
+ .size());
+
+
+ // REGRESSION test for read(ByteBuffer[], int, int) on special files
+ try {
+ FileChannel specialFile =
+ new FileInputStream("/dev/zero").getChannel();
+ assertEquals(0, specialFile.size());
+ ByteBuffer buf = ByteBuffer.allocate(8);
+ assertEquals(8, specialFile.read(buf));
+ ByteBuffer[] bufs = { ByteBuffer.allocate(8) };
+ assertEquals(8, specialFile.read(bufs, 0, 1));
+ specialFile.close();
+ } catch (FileNotFoundException e) {
+ // skip test if special file doesn't exist
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#size()
+ */
+ public void test_size_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.size();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.truncate(0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.truncate(0);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.truncate(-1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_IllegalArgument() throws Exception {
+ // regression test for Harmony-941
+ try {
+ readOnlyFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.truncate(-1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ_ReadOnly() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ try {
+ readOnlyFileChannel.truncate(readOnlyFileChannel.size());
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.truncate(0);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#truncate(long)
+ */
+ public void test_truncateJ() throws Exception {
+ writeDataToFile(fileOfReadWriteFileChannel);
+
+ int truncateLength = CONTENT_LENGTH + 2;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+ truncateLength = CONTENT_LENGTH;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(CONTENT_LENGTH, fileOfReadWriteFileChannel.length());
+
+ truncateLength = CONTENT_LENGTH / 2;
+ assertEquals(readWriteFileChannel, readWriteFileChannel
+ .truncate(truncateLength));
+ assertEquals(truncateLength, fileOfReadWriteFileChannel.length());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock()
+ */
+ public void test_lock() throws Exception {
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ // Verify that calling lock() leads to the method
+ // lock(long, long, boolean) being called with a 0 for the
+ // first parameter, Long.MAX_VALUE as the second parameter and false
+ // as the third parameter.
+ mockFileChannel.lock();
+ assertTrue(mockFileChannel.isLockCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.lock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException before IllegalArgumentException
+ try {
+ readWriteFileChannel.lock(-1, 0, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_IllegalArgument() throws Exception {
+ try {
+ writeOnlyFileChannel.lock(0, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.lock(-1, 0, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.lock(-1, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.lock(Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NonWritable() throws Exception {
+ try {
+ readOnlyFileChannel.lock(0, 10, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // throws NonWritableChannelException before IllegalArgumentException
+ try {
+ readOnlyFileChannel.lock(-1, 0, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NonReadable() throws Exception {
+ try {
+ writeOnlyFileChannel.lock(0, 10, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // throws NonReadableChannelException before IllegalArgumentException
+ try {
+ writeOnlyFileChannel.lock(-1, 0, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Shared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ // fileLock.isShared depends on whether the underlying platform support
+ // shared lock, but it works on Windows & Linux.
+ assertTrue(fileLock.isShared());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NotShared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+ assertFalse(fileLock.isShared());
+ assertSame(writeOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Long_MAX_VALUE() throws Exception {
+ final long POSITION = 0;
+ final long SIZE = Long.MAX_VALUE;
+ fileLock = readOnlyFileChannel.lock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ assertTrue(fileLock.isShared());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_Overlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+
+ try {
+ writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+ fail("should throw OverlappingFileLockException");
+ } catch (OverlappingFileLockException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long, long, boolean)
+ */
+ public void test_lockJJZ_NotOverlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ FileLock fileLock1 = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock1.isValid());
+ FileLock fileLock2 = writeOnlyFileChannel.lock(POSITION + SIZE, SIZE,
+ false);
+ assertTrue(fileLock2.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#lock(long,long,boolean)
+ */
+ public void test_lockJJZ_After_Release() throws Exception {
+ fileLock = writeOnlyFileChannel.lock(0, 10, false);
+ fileLock.release();
+ // after release file lock can be obtained again.
+ fileLock = writeOnlyFileChannel.lock(0, 10, false);
+ assertTrue(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock()
+ */
+ public void test_tryLock() throws Exception {
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ // Verify that calling tryLock() leads to the method
+ // tryLock(long, long, boolean) being called with a 0 for the
+ // first parameter, Long.MAX_VALUE as the second parameter and false
+ // as the third parameter.
+ mockFileChannel.tryLock();
+ assertTrue(mockFileChannel.isTryLockCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Closed() throws Exception {
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.tryLock(0, 10, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException before IllegalArgumentException
+ try {
+ readWriteFileChannel.tryLock(-1, 0, false);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_IllegalArgument() throws Exception {
+ try {
+ writeOnlyFileChannel.tryLock(0, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.tryLock(-1, 0, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.tryLock(-1, -1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.tryLock(Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NonWritable() throws Exception {
+ try {
+ readOnlyFileChannel.tryLock(0, 10, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // throws NonWritableChannelException before IllegalArgumentException
+ try {
+ readOnlyFileChannel.tryLock(-1, 0, false);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NonReadable() throws Exception {
+ try {
+ writeOnlyFileChannel.tryLock(0, 10, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // throws NonReadableChannelException before IllegalArgumentException
+ try {
+ writeOnlyFileChannel.tryLock(-1, 0, true);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Shared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ // fileLock.isShared depends on whether the underlying platform support
+ // shared lock, but it works on Windows & Linux.
+ assertTrue(fileLock.isShared());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NotShared() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.tryLock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+ assertFalse(fileLock.isShared());
+ assertSame(writeOnlyFileChannel, fileLock.channel());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Long_MAX_VALUE() throws Exception {
+ final long POSITION = 0;
+ final long SIZE = Long.MAX_VALUE;
+ fileLock = readOnlyFileChannel.tryLock(POSITION, SIZE, true);
+ assertTrue(fileLock.isValid());
+ assertTrue(fileLock.isShared());
+ assertEquals(POSITION, fileLock.position());
+ assertEquals(SIZE, fileLock.size());
+ assertSame(readOnlyFileChannel, fileLock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_Overlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ fileLock = writeOnlyFileChannel.lock(POSITION, SIZE, false);
+ assertTrue(fileLock.isValid());
+
+ try {
+ writeOnlyFileChannel.lock(POSITION + 1, SIZE, false);
+ fail("should throw OverlappingFileLockException");
+ } catch (OverlappingFileLockException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long, long, boolean)
+ */
+ public void test_tryLockJJZ_NotOverlapping() throws Exception {
+ final long POSITION = 100;
+ final long SIZE = 200;
+ FileLock fileLock1 = writeOnlyFileChannel
+ .tryLock(POSITION, SIZE, false);
+ assertTrue(fileLock1.isValid());
+
+ FileLock fileLock2 = writeOnlyFileChannel.tryLock(POSITION + SIZE,
+ SIZE, false);
+ assertTrue(fileLock2.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#tryLock(long,long,boolean)
+ */
+ public void test_tryLockJJZ_After_Release() throws Exception {
+ fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+ fileLock.release();
+
+ // after release file lock can be obtained again.
+ fileLock = writeOnlyFileChannel.tryLock(0, 10, false);
+ assertTrue(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_Null() throws Exception {
+ ByteBuffer readBuffer = null;
+
+ try {
+ readOnlyFileChannel.read(readBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_Closed() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first
+ readBuffer = null;
+ try {
+ readWriteFileChannel.read(readBuffer);
+ fail();
+ } catch (ClosedChannelException expected) {
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_readLByteBuffer_WriteOnly() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail();
+ } catch (NonReadableChannelException expected) {
+ }
+
+ readBuffer = null;
+ try {
+ writeOnlyFileChannel.read(readBuffer);
+ fail();
+ } catch (NonReadableChannelException expected) {
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_readLByteBuffer_EmptyFile() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer)
+ */
+ public void test_readLByteBuffer_LimitedCapacity() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(LIMITED_CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(LIMITED_CAPACITY, result);
+ assertEquals(LIMITED_CAPACITY, readBuffer.position());
+ readBuffer.flip();
+ for (int i = 0; i < LIMITED_CAPACITY; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ public void test_readLByteBuffer() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+ int result = readOnlyFileChannel.read(readBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffer.position());
+ readBuffer.flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ public void test_readLByteBufferJ_Null() throws Exception {
+ try {
+ readOnlyFileChannel.read(null, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ readWriteFileChannel.read(null, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_readLByteBufferJ_Closed() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffer, 0);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffer, 0);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ public void test_readLByteBufferJ_IllegalArgument() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.read(readBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void test_readLByteBufferJ_WriteOnly() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffer, 0);
+ fail();
+ } catch (NonReadableChannelException expected) {
+ }
+ }
+
+ public void test_readLByteBufferJ_Emptyfile() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer, 0);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ public void test_readLByteBufferJ_Position_BeyondFileLimit() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ int result = readOnlyFileChannel.read(readBuffer,
+ CONTENT_AS_BYTES.length);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffer.position());
+ }
+
+ public void test_readLByteBufferJ_Position_As_Long() throws Exception {
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+ try {
+ readOnlyFileChannel.read(readBuffer, Long.MAX_VALUE);
+ } catch (IOException expected) {
+ }
+ }
+
+ public void test_readLByteBufferJ() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer readBuffer = ByteBuffer.allocate(CAPACITY);
+
+ final int BUFFER_POSITION = 1;
+ readBuffer.position(BUFFER_POSITION);
+
+ final int POSITION = 2;
+ int result = readOnlyFileChannel.read(readBuffer, POSITION);
+ assertEquals(CONTENT_AS_BYTES_LENGTH - POSITION, result);
+ assertEquals(BUFFER_POSITION + result, readBuffer.position());
+
+ readBuffer.flip();
+ readBuffer.position(BUFFER_POSITION);
+ for (int i = POSITION; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer() throws Exception {
+ // regression test for Harmony-849
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ long readCount = readOnlyFileChannel.read(readBuffers);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readCount);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[0].position());
+ assertEquals(0, readBuffers[1].position());
+ readBuffers[0].flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[0].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer_mock() throws Exception {
+ FileChannel mockChannel = new MockFileChannel();
+ ByteBuffer[] buffers = new ByteBuffer[2];
+ mockChannel.read(buffers);
+ // Verify that calling read(ByteBuffer[] dsts) leads to the method
+ // read(dsts, 0, dsts.length)
+ assertTrue(((MockFileChannel)mockChannel).isReadCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Null() throws Exception {
+ ByteBuffer[] readBuffers = null;
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 1, 11);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Closed() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // regression test for Harmony-902
+ readBuffers[0] = null;
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_WriteOnly() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // first throws NonReadableChannelException.
+ readBuffers[0] = null;
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 1);
+ fail("should throw NonReadableChannelException");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_IndexOutOfBound() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.read(readBuffers, 2, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ readWriteFileChannel.read(null, -1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.read(readBuffers, 0, 3);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ readWriteFileChannel.read(readBuffers, -1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.read(readBuffers, 0, 3);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyFile() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+ long result = readOnlyFileChannel.read(readBuffers, 0, 2);
+ assertEquals(-1, result);
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(0, readBuffers[1].position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyBuffers() throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ try {
+ readOnlyFileChannel.read(readBuffers, 0, 2);
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ long result = readOnlyFileChannel.read(readBuffers, 0, 1);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_EmptyFile_EmptyBuffers()
+ throws Exception {
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ // will not throw NullPointerException
+ long result = readOnlyFileChannel.read(readBuffers, 0, 0);
+ assertEquals(0, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_Length_Zero() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ long result = readOnlyFileChannel.read(readBuffers, 1, 0);
+ assertEquals(0, result);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII_LimitedCapacity() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(LIMITED_CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(LIMITED_CAPACITY);
+
+ // reads to the second buffer
+ long result = readOnlyFileChannel.read(readBuffers, 1, 1);
+ assertEquals(LIMITED_CAPACITY, result);
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(LIMITED_CAPACITY, readBuffers[1].position());
+
+ readBuffers[1].flip();
+ for (int i = 0; i < LIMITED_CAPACITY; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read$LByteBufferII() throws Exception {
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ ByteBuffer[] readBuffers = new ByteBuffer[2];
+ readBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ readBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ // writes to the second buffer
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readOnlyFileChannel.read(
+ readBuffers, 1, 1));
+ assertEquals(0, readBuffers[0].position());
+ assertEquals(CONTENT_AS_BYTES_LENGTH, readBuffers[1].position());
+
+ readBuffers[1].flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffers[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#isOpen()
+ */
+ public void test_isOpen() throws Exception {
+ // Regression for HARMONY-40
+ File logFile = File.createTempFile("out", "tmp");
+ logFile.deleteOnExit();
+ FileOutputStream out = new FileOutputStream(logFile, true);
+ FileChannel channel = out.getChannel();
+ out.write(1);
+ out.close();
+ assertFalse("Assert 0: Channel is still open", channel.isOpen());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#position()
+ */
+ public void test_position_append() throws Exception {
+ // Regression test for Harmony-508
+ File tmpfile = File.createTempFile("FileOutputStream", "tmp");
+ tmpfile.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(tmpfile);
+ byte[] b = new byte[10];
+ for (int i = 0; i < b.length; i++) {
+ b[i] = (byte) i;
+ }
+ fos.write(b);
+ fos.flush();
+ fos.close();
+ FileOutputStream f = new FileOutputStream(tmpfile, true);
+ // Harmony expected 10, but the RI and Android report 0.
+ assertEquals(0, f.getChannel().position());
+ }
+
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_AbnormalMode() throws IOException {
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ try {
+ writeOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException ex) {
+ // expected;
+ }
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, CONTENT_LENGTH);
+ fail("should throw NonWritableChannelException .");
+ } catch (NonWritableChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.PRIVATE, 0, CONTENT_LENGTH);
+ fail("should throw NonWritableChannelException .");
+ } catch (NonWritableChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, -1, CONTENT_LENGTH);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH + 1);
+ fail();
+ } catch (NonWritableChannelException expected) {
+ } catch (IOException expected) {
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+ fail();
+ } catch (NonWritableChannelException expected) {
+ } catch (IOException expected) {
+ }
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+ try {
+ readOnlyFileChannel.map(MapMode.READ_ONLY, 2, CONTENT_LENGTH - 1);
+ fail("should throw IOException.");
+ } catch (IOException ex) {
+ // expected;
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.map(MapMode.READ_WRITE, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly_CloseChannel() throws IOException {
+ // close channel has no effect on map if mapped
+ assertEquals(0, readWriteFileChannel.size());
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_ONLY,
+ 0, CONTENT_LENGTH);
+ assertEquals(CONTENT_LENGTH, readWriteFileChannel.size());
+ readOnlyFileChannel.close();
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private_CloseChannel() throws IOException {
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+ CONTENT_LENGTH);
+ readWriteFileChannel.close();
+ mapped.put(TEST_BYTES);
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals("test".length(), mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly() throws IOException {
+ MappedByteBuffer mapped = null;
+ // try put something to readonly map
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ mapped = readOnlyFileChannel.map(MapMode.READ_ONLY, 0, CONTENT_LENGTH);
+ try {
+ mapped.put(TEST_BYTES);
+ fail("should throw ReadOnlyBufferException.");
+ } catch (ReadOnlyBufferException ex) {
+ // expected;
+ }
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals(CONTENT_LENGTH, mapped.capacity());
+ assertEquals(0, mapped.position());
+
+ // try to get a readonly map from read/write channel
+ writeDataToFile(fileOfReadWriteFileChannel);
+ mapped = readWriteFileChannel.map(MapMode.READ_ONLY, 0, CONTENT
+ .length());
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ assertEquals(CONTENT_LENGTH, mapped.capacity());
+ assertEquals(0, mapped.position());
+
+ // map not change channel's position
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(0, readWriteFileChannel.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadOnly_NonZeroPosition() throws IOException {
+ this.writeDataToFile(fileOfReadOnlyFileChannel);
+ MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+ 10, CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private() throws IOException {
+ this.writeDataToFile(fileOfReadWriteFileChannel);
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 0,
+ CONTENT_LENGTH);
+ assertEquals(CONTENT_LENGTH, mapped.limit());
+ // test copy on write if private
+ ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+ assertSame(returnByPut, mapped);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ mapped.force();
+ readWriteFileChannel.read(checkBuffer);
+ assertEquals(CONTENT, new String(checkBuffer.array(), "iso8859-1"));
+
+ // test overflow
+ try {
+ mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_Private_NonZeroPosition() throws IOException {
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.PRIVATE, 10,
+ CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT_LENGTH - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadWrite() throws IOException {
+ MappedByteBuffer mapped = null;
+ writeDataToFile(fileOfReadWriteFileChannel);
+ mapped = readWriteFileChannel.map(MapMode.READ_WRITE, 0, CONTENT
+ .length());
+
+ // put something will change its channel
+ ByteBuffer returnByPut = mapped.put(TEST_BYTES);
+ assertSame(returnByPut, mapped);
+ String checkString = "test" + CONTENT.substring(4);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ mapped.force();
+ readWriteFileChannel.position(0);
+ readWriteFileChannel.read(checkBuffer);
+ assertEquals(checkString, new String(checkBuffer.array(), "iso8859-1"));
+
+ try {
+ mapped.put(("test" + CONTENT).getBytes("iso8859-1"));
+ fail("should throw BufferOverflowException.");
+ } catch (BufferOverflowException ex) {
+ // expected;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_ReadWrite_NonZeroPosition() throws IOException {
+ // test position non-zero
+ writeDataToFile(fileOfReadWriteFileChannel);
+ MappedByteBuffer mapped = readWriteFileChannel.map(MapMode.READ_WRITE,
+ 10, CONTENT_LENGTH - 10);
+ assertEquals(CONTENT_LENGTH - 10, mapped.limit());
+ assertEquals(CONTENT.length() - 10, mapped.capacity());
+ assertEquals(0, mapped.position());
+ mapped.put(TEST_BYTES);
+ ByteBuffer checkBuffer = ByteBuffer.allocate(CONTENT_LENGTH);
+ readWriteFileChannel.read(checkBuffer);
+ String expected = CONTENT.substring(0, 10) + "test"
+ + CONTENT.substring(10 + "test".length());
+ assertEquals(expected, new String(checkBuffer.array(), "iso8859-1"));
+ }
+
+ /**
+ * Tests map() method for the value of positions exceeding memory
+ * page size and allocation granularity size.
+ *
+ * @tests java.nio.channels.FileChannel#map(MapMode,long,long)
+ */
+ public void test_map_LargePosition() throws IOException {
+ // Regression test for HARMONY-3085
+ int[] sizes = {
+ 4096, // 4K size (normal page size for Linux & Windows)
+ 65536, // 64K size (alocation granularity size for Windows)
+ };
+ final int CONTENT_LEN = 10;
+
+ for (int i = 0; i < sizes.length; ++i) {
+ // reset the file and the channel for the iterations
+ // (for the first iteration it was done by setUp()
+ if (i > 0 ) {
+ fileOfReadOnlyFileChannel = File.createTempFile(
+ "File_of_readOnlyFileChannel", "tmp");
+ fileOfReadOnlyFileChannel.deleteOnExit();
+ readOnlyFileChannel = new FileInputStream(fileOfReadOnlyFileChannel)
+ .getChannel();
+ }
+
+ writeLargeDataToFile(fileOfReadOnlyFileChannel, sizes[i] + 2 * CONTENT_LEN);
+ MappedByteBuffer mapped = readOnlyFileChannel.map(MapMode.READ_ONLY,
+ sizes[i], CONTENT_LEN);
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (capacity)", CONTENT_LEN, mapped.capacity());
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (limit)", CONTENT_LEN, mapped.limit());
+ assertEquals("Incorrectly mapped file channel for " + sizes[i]
+ + " position (position)", 0, mapped.position());
+
+ // map not change channel's position
+ assertEquals(0, readOnlyFileChannel.position());
+
+ // Close the file and the channel before the next iteration
+ readOnlyFileChannel.close();
+ fileOfReadOnlyFileChannel.delete();
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_Null() throws Exception {
+ ByteBuffer writeBuffer = null;
+
+ try {
+ writeOnlyFileChannel.write(writeBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffer);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_Closed() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ writeBuffer = null;
+ try {
+ readWriteFileChannel.read(writeBuffer);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_ReadOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // first throws NonWriteableChannelException
+ writeBuffer = null;
+ try {
+ readOnlyFileChannel.write(writeBuffer);
+ fail("should throw NonWritableChannelException");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ int result = writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer)
+ */
+ public void test_writeLByteBuffer_positioned() throws Exception {
+ final int pos = 5;
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeBuffer.position(pos);
+ int result = writeOnlyFileChannel.write(writeBuffer);
+ assertEquals(CONTENT_AS_BYTES_LENGTH - pos, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH - pos, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH - pos];
+ fis.read(inputBuffer);
+ String test = CONTENT.substring(pos);
+ assertTrue(Arrays.equals(test.getBytes("iso8859-1"), inputBuffer));
+ }
+
+ public void test_writeLByteBufferJ_Null() throws Exception {
+ try {
+ readWriteFileChannel.write(null, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (NonWritableChannelException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.write(null, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ readWriteFileChannel.write(null, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_writeLByteBufferJ_Closed() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffer, 0);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffer, 0);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ public void test_writeLByteBufferJ_ReadOnly() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+ try {
+ readOnlyFileChannel.write(writeBuffer, 10);
+ fail();
+ } catch (NonWritableChannelException expected) {
+ }
+ }
+
+ public void test_writeLByteBufferJ_IllegalArgument() throws Exception {
+ ByteBuffer writeBuffer = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.write(writeBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffer, -1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer,long)
+ */
+ public void test_writeLByteBufferJ() throws Exception {
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int POSITION = 4;
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ int result = writeOnlyFileChannel.write(writeBuffer, POSITION);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffer.position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(POSITION + CONTENT_AS_BYTES_LENGTH,
+ fileOfWriteOnlyFileChannel.length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ byte[] expectedResult = new byte[POSITION + CONTENT_AS_BYTES_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, POSITION,
+ CONTENT_AS_BYTES_LENGTH);
+ assertTrue(Arrays.equals(expectedResult, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ MockFileChannel mockFileChannel = new MockFileChannel();
+ mockFileChannel.write(writeBuffers);
+ // verify that calling write(ByteBuffer[] srcs) leads to the method
+ // write(srcs, 0, srcs.length)
+ assertTrue(mockFileChannel.isWriteCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_Null() throws Exception {
+ ByteBuffer[] writeBuffers = null;
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffers, 1, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // first throws NullPointerException
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 0);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_Closed() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // throws ClosedChannelException first
+ writeBuffers[0] = null;
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_ReadOnly() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.allocate(CAPACITY);
+ writeBuffers[1] = ByteBuffer.allocate(CAPACITY);
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail();
+ } catch (NonWritableChannelException e) {
+ }
+
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ writeBuffers = null;
+ try {
+ readOnlyFileChannel.write(writeBuffers, 0, 1);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ readOnlyFileChannel.close();
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_EmptyBuffers() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ try {
+ writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.write(writeBuffers, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII() throws Exception {
+ ByteBuffer[] writeBuffers = new ByteBuffer[2];
+ writeBuffers[0] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ writeBuffers[1] = ByteBuffer.wrap(CONTENT_AS_BYTES);
+
+ long result = writeOnlyFileChannel.write(writeBuffers, 0, 2);
+ assertEquals(CONTENT_AS_BYTES_LENGTH * 2, result);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[0].position());
+ assertEquals(CONTENT_AS_BYTES_LENGTH, writeBuffers[1].position());
+ writeOnlyFileChannel.close();
+
+ assertEquals(CONTENT_AS_BYTES_LENGTH * 2, fileOfWriteOnlyFileChannel
+ .length());
+
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] inputBuffer = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(inputBuffer);
+ byte[] expectedResult = new byte[CONTENT_AS_BYTES_LENGTH * 2];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult, 0,
+ CONTENT_AS_BYTES_LENGTH);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedResult,
+ CONTENT_AS_BYTES_LENGTH, CONTENT_AS_BYTES_LENGTH);
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, inputBuffer));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_Closed()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SourceClosed()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ readByteChannel.close();
+
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, 10);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, 0, -1);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_IllegalArgument()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ try {
+ writeOnlyFileChannel.transferFrom(readByteChannel, 10, -1);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferFrom(readByteChannel, -1, -10);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_NonWritable()
+ throws Exception {
+ readByteChannel = DatagramChannel.open();
+ try {
+ readOnlyFileChannel.transferFrom(readByteChannel, 0, 0);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SourceNonReadable()
+ throws Exception {
+ try {
+ readWriteFileChannel.transferFrom(writeOnlyFileChannel, 0, 0);
+ fail("should throw NonReadableChannelException.");
+ } catch (NonReadableChannelException e) {
+ // expected
+ }
+
+ // not throws NonReadableChannelException first if position beyond file
+ // size.
+ readWriteFileChannel.transferFrom(writeOnlyFileChannel, 10, 10);
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_PositionBeyondSize()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+
+ final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+ final int LENGTH = 5;
+ long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+ POSITION, LENGTH);
+ assertEquals(0, result);
+ assertEquals(0, writeOnlyFileChannel.position());
+ assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+ .position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_FileChannel()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ final int WRITEONLYFILECHANNELPOSITION = 4;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = 3;
+ final int LENGTH = 5;
+ long result = writeOnlyFileChannel.transferFrom(readOnlyFileChannel,
+ POSITION, LENGTH);
+ assertEquals(LENGTH, result);
+ assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+ .position());
+ assertEquals(READONLYFILECHANNELPOSITION + LENGTH, readOnlyFileChannel
+ .position());
+ writeOnlyFileChannel.close();
+
+ final int EXPECTED_LENGTH = POSITION + LENGTH;
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultContent = new byte[EXPECTED_LENGTH];
+ fis.read(resultContent);
+
+ byte[] expectedContent = new byte[EXPECTED_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0, POSITION);
+ System.arraycopy(CONTENT_AS_BYTES, READONLYFILECHANNELPOSITION,
+ expectedContent, POSITION, LENGTH);
+ assertTrue(Arrays.equals(expectedContent, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_DatagramChannel()
+ throws Exception {
+ // connects two datagramChannels.
+ datagramChannelReceiver = DatagramChannel.open();
+ datagramChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender = DatagramChannel.open();
+ datagramChannelSender.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ datagramChannelReceiver.connect(datagramChannelSender.socket()
+ .getLocalSocketAddress());
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ // sends data from datagramChannelSender to datagramChannelReceiver.
+ datagramChannelSender.send(writeBuffer, datagramChannelReceiver
+ .socket().getLocalSocketAddress());
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+
+ // transfers data from datagramChannelReceiver to fileChannel.
+ long result = writeOnlyFileChannel.transferFrom(
+ datagramChannelReceiver, 0, CONTENT_AS_BYTES_LENGTH);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, writeOnlyFileChannel.position());
+ writeOnlyFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfWriteOnlyFileChannel
+ .length());
+ byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(resultContent);
+
+ // compares contents.
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_SocketChannel()
+ throws Exception {
+ // connects two socketChannels.
+ socketChannelReceiver = SocketChannel.open();
+ serverSocketChannel = ServerSocketChannel.open();
+ serverSocketChannel.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ socketChannelReceiver.connect(serverSocketChannel.socket()
+ .getLocalSocketAddress());
+ serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+ socketChannelSender = serverSocketChannel.accept();
+ socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+ // sends data from socketChannelSender to socketChannelReceiver.
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ socketChannelSender.write(writeBuffer);
+
+ // transfers data from socketChannelReceiver to fileChannel.
+ long result = readWriteFileChannel.transferFrom(socketChannelReceiver,
+ 0, CONTENT_AS_BYTES_LENGTH);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, readWriteFileChannel.position());
+ readWriteFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfReadWriteFileChannel);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, fileOfReadWriteFileChannel
+ .length());
+ byte[] resultContent = new byte[CONTENT_AS_BYTES_LENGTH];
+ fis.read(resultContent);
+
+ // compares content.
+ assertTrue(Arrays.equals(CONTENT_AS_BYTES, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferFrom(ReadableByteChannel,long,long)
+ */
+ public void test_transferFromLReadableByteChannelJJ_Pipe() throws Exception {
+ // inits data in file.
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // inits pipe.
+ pipe = Pipe.open();
+
+ // writes content to pipe.
+ ByteBuffer writeBuffer = ByteBuffer.wrap(CONTENT_AS_BYTES);
+ pipe.sink().write(writeBuffer);
+
+ // transfers data from pipe to fileChannel.
+ final int OFFSET = 2;
+ final int LENGTH = 4;
+ long result = writeOnlyFileChannel.transferFrom(pipe.source(), OFFSET,
+ LENGTH);
+ assertEquals(LENGTH, result);
+ writeOnlyFileChannel.close();
+
+ // gets content from file.
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultBytes = new byte[OFFSET + LENGTH];
+ fis.read(resultBytes);
+
+ // compares content.
+ byte[] expectedBytes = new byte[OFFSET + LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, 0, OFFSET);
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedBytes, OFFSET, LENGTH);
+
+ assertTrue(Arrays.equals(expectedBytes, resultBytes));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Null() throws Exception {
+ writableByteChannel = null;
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (NonReadableChannelException expected) {
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ readOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferTo(-1, 0, writableByteChannel);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (NonReadableChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Closed() throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ readOnlyFileChannel.close();
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ writeOnlyFileChannel.close();
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ readWriteFileChannel.close();
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // should throw ClosedChannelException first.
+ try {
+ readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+ fail("should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ public void test_transferToJJLWritableByteChannel_SourceClosed() throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ writableByteChannel.close();
+
+ try {
+ readOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (ClosedChannelException expected) {
+ } catch (NonReadableChannelException expected) {
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, -1, writableByteChannel);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_IllegalArgument()
+ throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ try {
+ readOnlyFileChannel.transferTo(10, -1, writableByteChannel);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(-1, -10, writableByteChannel);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ public void test_transferToJJLWritableByteChannel_NonReadable() throws Exception {
+ writableByteChannel = DatagramChannel.open();
+ try {
+ writeOnlyFileChannel.transferTo(0, 10, writableByteChannel);
+ fail();
+ } catch (NonReadableChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_TargetNonWritable()
+ throws Exception {
+ try {
+ readWriteFileChannel.transferTo(0, 0, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // first throws NonWritableChannelException even position out of file
+ // size.
+ try {
+ readWriteFileChannel.transferTo(10, 10, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ // regression test for Harmony-941
+ // first throws NonWritableChannelException even arguments are illegal.
+ try {
+ readWriteFileChannel.transferTo(-1, 10, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+
+ try {
+ readWriteFileChannel.transferTo(0, -1, readOnlyFileChannel);
+ fail("should throw NonWritableChannelException.");
+ } catch (NonWritableChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_PositionBeyondSize()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int WRITEONLYFILECHANNELPOSITION = 2;
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = CONTENT_AS_BYTES_LENGTH * 2;
+ final int LENGTH = 5;
+ long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+ writeOnlyFileChannel);
+ assertEquals(0, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ assertEquals(WRITEONLYFILECHANNELPOSITION, writeOnlyFileChannel
+ .position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_FileChannel()
+ throws Exception {
+ // init data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ final int READONLYFILECHANNELPOSITION = 2;
+ final int WRITEONLYFILECHANNELPOSITION = 4;
+ readOnlyFileChannel.position(READONLYFILECHANNELPOSITION);
+ writeOnlyFileChannel.position(WRITEONLYFILECHANNELPOSITION);
+
+ final int POSITION = 3;
+ final int LENGTH = 5;
+ long result = readOnlyFileChannel.transferTo(POSITION, LENGTH,
+ writeOnlyFileChannel);
+ assertEquals(LENGTH, result);
+ assertEquals(READONLYFILECHANNELPOSITION, readOnlyFileChannel
+ .position());
+ assertEquals(WRITEONLYFILECHANNELPOSITION + LENGTH,
+ writeOnlyFileChannel.position());
+ writeOnlyFileChannel.close();
+
+ final int EXPECTED_LENGTH = WRITEONLYFILECHANNELPOSITION + LENGTH;
+ fis = new FileInputStream(fileOfWriteOnlyFileChannel);
+ byte[] resultContent = new byte[EXPECTED_LENGTH];
+ fis.read(resultContent);
+
+ byte[] expectedContent = new byte[EXPECTED_LENGTH];
+ System.arraycopy(CONTENT_AS_BYTES, 0, expectedContent, 0,
+ WRITEONLYFILECHANNELPOSITION);
+ System.arraycopy(CONTENT_AS_BYTES, POSITION, expectedContent,
+ WRITEONLYFILECHANNELPOSITION, LENGTH);
+ assertTrue(Arrays.equals(expectedContent, resultContent));
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_SocketChannel()
+ throws Exception {
+ // inits data into file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // connects two socketChannels.
+ socketChannelReceiver = SocketChannel.open();
+ socketChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ serverSocketChannel = ServerSocketChannel.open();
+ serverSocketChannel.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ socketChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ socketChannelReceiver.connect(serverSocketChannel.socket()
+ .getLocalSocketAddress());
+ serverSocketChannel.socket().setSoTimeout(TIME_OUT);
+ socketChannelSender = serverSocketChannel.accept();
+ socketChannelSender.socket().setSoTimeout(TIME_OUT);
+
+ // position here should have no effect on transferTo since it uses
+ // offset from file_begin
+ final int POSITION = 10;
+ readOnlyFileChannel.position(POSITION);
+
+ // transfers data from file to socketChannelSender.
+ final int OFFSET = 2;
+ long result = readOnlyFileChannel.transferTo(OFFSET,
+ CONTENT_AS_BYTES_LENGTH * 2, socketChannelSender);
+ final int LENGTH = CONTENT_AS_BYTES_LENGTH - OFFSET;
+ assertEquals(LENGTH, result);
+ assertEquals(POSITION, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+ socketChannelSender.close();
+
+ // gets contents from socketChannelReceiver.
+ ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH + 1);
+ int totalRead = 0;
+ int countRead = 0;
+ long beginTime = System.currentTimeMillis();
+ while ((countRead = socketChannelReceiver.read(readBuffer)) != -1) {
+ totalRead += countRead;
+ // TIMEOUT
+ if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+ break;
+ }
+ }
+ assertEquals(LENGTH, totalRead);
+
+ // compares contents.
+ readBuffer.flip();
+ for (int i = OFFSET; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_DatagramChannel()
+ throws Exception {
+ // inits data to file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // connects two datagramChannel
+ datagramChannelReceiver = DatagramChannel.open();
+ datagramChannelReceiver.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender = DatagramChannel.open();
+ datagramChannelSender.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0));
+ datagramChannelSender.socket().setSoTimeout(TIME_OUT);
+ datagramChannelSender.connect(datagramChannelReceiver.socket()
+ .getLocalSocketAddress());
+ datagramChannelReceiver.socket().setSoTimeout(TIME_OUT);
+ datagramChannelReceiver.connect(datagramChannelSender.socket()
+ .getLocalSocketAddress());
+
+ // transfers data from fileChannel to datagramChannelSender
+ long result = readOnlyFileChannel.transferTo(0,
+ CONTENT_AS_BYTES_LENGTH, datagramChannelSender);
+ assertEquals(CONTENT_AS_BYTES_LENGTH, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+ datagramChannelSender.close();
+
+ // gets contents from datagramChannelReceiver
+ ByteBuffer readBuffer = ByteBuffer.allocate(CONTENT_AS_BYTES_LENGTH);
+ long beginTime = System.currentTimeMillis();
+ int totalRead = 0;
+ while (totalRead < CONTENT_AS_BYTES_LENGTH) {
+ totalRead += datagramChannelReceiver.read(readBuffer);
+ if (System.currentTimeMillis() - beginTime > TIME_OUT) {
+ break;
+ }
+ }
+ assertEquals(CONTENT_AS_BYTES_LENGTH, totalRead);
+
+ // compares contents.
+ readBuffer.flip();
+ for (int i = 0; i < CONTENT_AS_BYTES_LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileChannel#transferTo(long,long,WritableByteChannel)
+ */
+ public void test_transferToJJLWritableByteChannel_Pipe() throws Exception {
+ // inits data in file.
+ writeDataToFile(fileOfReadOnlyFileChannel);
+
+ // inits pipe.
+ pipe = Pipe.open();
+
+ // transfers data from fileChannel to pipe.
+ final int OFFSET = 2;
+ final int LENGTH = 4;
+ long result = readOnlyFileChannel.transferTo(OFFSET, LENGTH, pipe
+ .sink());
+ assertEquals(LENGTH, result);
+ assertEquals(0, readOnlyFileChannel.position());
+ readOnlyFileChannel.close();
+
+ // gets content from pipe.
+ ByteBuffer readBuffer = ByteBuffer.allocate(LENGTH);
+ result = pipe.source().read(readBuffer);
+ assertEquals(LENGTH, result);
+
+ // compares content.
+ readBuffer.flip();
+ for (int i = OFFSET; i < OFFSET + LENGTH; i++) {
+ assertEquals(CONTENT_AS_BYTES[i], readBuffer.get());
+ }
+ }
+
+ /**
+ * Regression test for Harmony-3324
+ * Make sure we could delete the file after we called transferTo() method.
+ */
+ public void test_transferTo_couldDelete() throws Exception {
+ // init data in files
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // call transferTo() method
+ readOnlyFileChannel.transferTo(0 , 2, writeOnlyFileChannel);
+
+ // delete both files
+ readOnlyFileChannel.close();
+ writeOnlyFileChannel.close();
+ boolean rDel = fileOfReadOnlyFileChannel.delete();
+ boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+ // make sure both files were deleted
+ assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+ assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+ }
+
+ /**
+ * Regression test for Harmony-3324
+ * Make sure we could delete the file after we called transferFrom() method.
+ */
+ public void test_transferFrom_couldDelete() throws Exception {
+ // init data in files
+ writeDataToFile(fileOfReadOnlyFileChannel);
+ writeDataToFile(fileOfWriteOnlyFileChannel);
+
+ // call transferTo() method
+ writeOnlyFileChannel.transferFrom(readOnlyFileChannel, 0 , 2);
+
+ // delete both files
+ readOnlyFileChannel.close();
+ writeOnlyFileChannel.close();
+ boolean rDel = fileOfReadOnlyFileChannel.delete();
+ boolean wDel = fileOfWriteOnlyFileChannel.delete();
+
+ // make sure both files were deleted
+ assertTrue("File " + readOnlyFileChannel + " exists", rDel);
+ assertTrue("File " + writeOnlyFileChannel + " exists", wDel);
+ }
+
+ private class MockFileChannel extends FileChannel {
+
+ private boolean isLockCalled = false;
+
+ private boolean isTryLockCalled = false;
+
+ private boolean isReadCalled = false;
+
+ private boolean isWriteCalled = false;
+
+ public void force(boolean arg0) throws IOException {
+ // do nothing
+ }
+
+ public FileLock lock(long position, long size, boolean shared)
+ throws IOException {
+ // verify that calling lock() leads to the method
+ // lock(0, Long.MAX_VALUE, false).
+ if (0 == position && Long.MAX_VALUE == size && false == shared) {
+ isLockCalled = true;
+ }
+ return null;
+ }
+
+ public MappedByteBuffer map(MapMode arg0, long arg1, long arg2)
+ throws IOException {
+ return null;
+ }
+
+ public long position() throws IOException {
+ return 0;
+ }
+
+ public FileChannel position(long arg0) throws IOException {
+ return null;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public int read(ByteBuffer arg0, long arg1) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] srcs, int offset, int length)
+ throws IOException {
+ // verify that calling read(ByteBuffer[] srcs) leads to the method
+ // read(srcs, 0, srcs.length)
+ if (0 == offset && length == srcs.length) {
+ isReadCalled = true;
+ }
+ return 0;
+ }
+
+ public long size() throws IOException {
+ return 0;
+ }
+
+ public long transferFrom(ReadableByteChannel arg0, long arg1, long arg2)
+ throws IOException {
+ return 0;
+ }
+
+ public long transferTo(long arg0, long arg1, WritableByteChannel arg2)
+ throws IOException {
+ return 0;
+ }
+
+ public FileChannel truncate(long arg0) throws IOException {
+ return null;
+ }
+
+ public FileLock tryLock(long position, long size, boolean shared)
+ throws IOException {
+ // verify that calling tryLock() leads to the method
+ // tryLock(0, Long.MAX_VALUE, false).
+ if (0 == position && Long.MAX_VALUE == size && false == shared) {
+ isTryLockCalled = true;
+ }
+ return null;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0, long arg1) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] srcs, int offset, int length)
+ throws IOException {
+ // verify that calling write(ByteBuffer[] srcs) leads to the method
+ // write(srcs, 0, srcs.length)
+ if(0 == offset && length == srcs.length){
+ isWriteCalled = true;
+ }
+ return 0;
+ }
+
+ protected void implCloseChannel() throws IOException {
+
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
new file mode 100644
index 0000000..b60096c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockInterruptionExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.FileLockInterruptionException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for FileLockInterruptionException
+ */
+public class FileLockInterruptionExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.FileLockInterruptionException#FileLockInterruptionException()}
+ */
+ public void test_Constructor() {
+ FileLockInterruptionException e = new FileLockInterruptionException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new FileLockInterruptionException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this,
+ new FileLockInterruptionException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
new file mode 100644
index 0000000..12142e8
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/FileLockTest.java
@@ -0,0 +1,199 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests class FileLock.
+ */
+public class FileLockTest extends TestCase {
+
+ private FileChannel readWriteChannel;
+
+ private MockFileLock mockLock;
+
+ class MockFileLock extends FileLock {
+
+ boolean isValid = true;
+
+ protected MockFileLock(FileChannel channel, long position, long size,
+ boolean shared) {
+ super(channel, position, size, shared);
+ }
+
+ public boolean isValid() {
+ return isValid;
+ }
+
+ public void release() throws IOException {
+ isValid = false;
+ }
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ File tempFile = File.createTempFile("testing", "tmp");
+ tempFile.deleteOnExit();
+ RandomAccessFile randomAccessFile = new RandomAccessFile(tempFile, "rw");
+ readWriteChannel = randomAccessFile.getChannel();
+ mockLock = new MockFileLock(readWriteChannel, 10, 100, false);
+ }
+
+ protected void tearDown() throws IOException {
+ if (readWriteChannel != null) {
+ readWriteChannel.close();
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#FileLock(FileChannel, long, long,
+ * boolean)
+ */
+ public void test_Constructor_Ljava_nio_channels_FileChannelJJZ() {
+ FileLock fileLock1 = new MockFileLock(null, 0, 0, false);
+ assertNull(fileLock1.channel());
+
+ try {
+ new MockFileLock(readWriteChannel, -1, 0, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ new MockFileLock(readWriteChannel, 0, -1, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ // Harmony-682 regression test
+ try {
+ new MockFileLock(readWriteChannel, Long.MAX_VALUE, 1, false);
+ fail("should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#channel()
+ */
+ public void test_channel() {
+ assertSame(readWriteChannel, mockLock.channel());
+ FileLock lock = new MockFileLock(null, 0, 10, true);
+ assertNull(lock.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#position()
+ */
+ public void test_position() {
+ FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+ assertEquals(20, fileLock1.position());
+
+ final long position = ((long) Integer.MAX_VALUE + 1);
+ FileLock fileLock2 = new MockFileLock(readWriteChannel, position, 100,
+ true);
+ assertEquals(position, fileLock2.position());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#size()
+ */
+ public void test_size() {
+ FileLock fileLock1 = new MockFileLock(readWriteChannel, 20, 100, true);
+ assertEquals(100, fileLock1.size());
+
+ final long position = 0x0FFFFFFFFFFFFFFFL;
+ final long size = ((long) Integer.MAX_VALUE + 1);
+ FileLock fileLock2 = new MockFileLock(readWriteChannel, position, size,
+ true);
+ assertEquals(size, fileLock2.size());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#isShared()
+ */
+ public void test_isShared() {
+ assertFalse(mockLock.isShared());
+ FileLock lock = new MockFileLock(null, 0, 10, true);
+ assertTrue(lock.isShared());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#overlaps(long, long)
+ */
+ public void test_overlaps_JJ() {
+ assertTrue(mockLock.overlaps(0, 11));
+ assertFalse(mockLock.overlaps(0, 10));
+ assertTrue(mockLock.overlaps(100, 110));
+ assertTrue(mockLock.overlaps(99, 110));
+ assertFalse(mockLock.overlaps(-1, 10));
+ //Harmony-671 regression test
+ assertTrue(mockLock.overlaps(1, 120));
+ assertTrue(mockLock.overlaps(20, 50));
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#isValid()
+ */
+ public void test_isValid() throws IOException {
+ FileLock fileLock = readWriteChannel.lock();
+ assertTrue(fileLock.isValid());
+ fileLock.release();
+ assertFalse(fileLock.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.FileLock#release()
+ */
+ public void test_release() throws Exception {
+ File file = File.createTempFile("test", "tmp");
+ file.deleteOnExit();
+ FileOutputStream fout = new FileOutputStream(file);
+ FileChannel fileChannel = fout.getChannel();
+ FileLock fileLock = fileChannel.lock();
+ fileChannel.close();
+ try {
+ fileLock.release();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ // release after release
+ fout = new FileOutputStream(file);
+ fileChannel = fout.getChannel();
+ fileLock = fileChannel.lock();
+ fileLock.release();
+ fileChannel.close();
+ try {
+ fileLock.release();
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ //expected
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
new file mode 100644
index 0000000..a8cdf83
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalBlockingModeExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.IllegalBlockingModeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalBlockingModeException
+ */
+public class IllegalBlockingModeExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.IllegalBlockingModeException#IllegalBlockingModeException()}
+ */
+ public void test_Constructor() {
+ IllegalBlockingModeException e = new IllegalBlockingModeException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalBlockingModeException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new IllegalBlockingModeException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
new file mode 100644
index 0000000..2fa3171
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/IllegalSelectorExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.IllegalSelectorException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for IllegalSelectorException
+ */
+public class IllegalSelectorExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.IllegalSelectorException#IllegalSelectorException()}
+ */
+ public void test_Constructor() {
+ IllegalSelectorException e = new IllegalSelectorException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalSelectorException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new IllegalSelectorException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
new file mode 100644
index 0000000..33234eb
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MapModeTest.java
@@ -0,0 +1,52 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.FileChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for FileChannel.MapMode
+ */
+public class MapModeTest extends TestCase {
+
+ /**
+ * java.nio.channels.FileChannel.MapMode#PRIVATE,READONLY,READWRITE
+ */
+ public void test_PRIVATE_READONLY_READWRITE() {
+ assertNotNull(FileChannel.MapMode.PRIVATE);
+ assertNotNull(FileChannel.MapMode.READ_ONLY);
+ assertNotNull(FileChannel.MapMode.READ_WRITE);
+
+ assertFalse(FileChannel.MapMode.PRIVATE
+ .equals(FileChannel.MapMode.READ_ONLY));
+ assertFalse(FileChannel.MapMode.PRIVATE
+ .equals(FileChannel.MapMode.READ_WRITE));
+ assertFalse(FileChannel.MapMode.READ_ONLY
+ .equals(FileChannel.MapMode.READ_WRITE));
+ }
+
+ /**
+ * java.nio.channels.FileChannel.MapMode#toString()
+ */
+ public void test_toString() {
+ assertNotNull(FileChannel.MapMode.PRIVATE.toString());
+ assertNotNull(FileChannel.MapMode.READ_ONLY.toString());
+ assertNotNull(FileChannel.MapMode.READ_WRITE.toString());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
new file mode 100644
index 0000000..c8dc2af
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockDatagramChannel.java
@@ -0,0 +1,81 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.DatagramSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.DatagramChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockDatagramChannel extends DatagramChannel {
+
+ public MockDatagramChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public DatagramSocket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public DatagramChannel connect(SocketAddress arg0) throws IOException {
+ return null;
+ }
+
+ public DatagramChannel disconnect() throws IOException {
+ return null;
+ }
+
+ public SocketAddress receive(ByteBuffer arg0) throws IOException {
+ return null;
+ }
+
+ public int send(ByteBuffer arg0, SocketAddress arg1) throws IOException {
+ return 0;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ // empty
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ // empty
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
new file mode 100644
index 0000000..2058a7a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockServerSocketChannel.java
@@ -0,0 +1,46 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockServerSocketChannel extends ServerSocketChannel {
+
+ protected MockServerSocketChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public ServerSocket socket() {
+ return null;
+ }
+
+ public SocketChannel accept() throws IOException {
+ return null;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
new file mode 100644
index 0000000..9d130ca
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/MockSocketChannel.java
@@ -0,0 +1,75 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+class MockSocketChannel extends SocketChannel {
+
+ protected MockSocketChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public Socket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public boolean isConnectionPending() {
+ return false;
+ }
+
+ public boolean connect(SocketAddress arg0) throws IOException {
+ return false;
+ }
+
+ public boolean finishConnect() throws IOException {
+ return false;
+ }
+
+ public int read(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ public int write(ByteBuffer arg0) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] arg0, int arg1, int arg2) throws IOException {
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
new file mode 100644
index 0000000..2ba7ba6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NoConnectionPendingExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.NoConnectionPendingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NoConnectionPendingException
+ */
+public class NoConnectionPendingExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.NoConnectionPendingException#NoConnectionPendingException()}
+ */
+ public void test_Constructor() {
+ NoConnectionPendingException e = new NoConnectionPendingException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NoConnectionPendingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new NoConnectionPendingException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
new file mode 100644
index 0000000..8c44f17
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonReadableChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.NonReadableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonReadableChannelException
+ */
+public class NonReadableChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.NonReadableChannelException#NonReadableChannelException()}
+ */
+ public void test_Constructor() {
+ NonReadableChannelException e = new NonReadableChannelException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NonReadableChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NonReadableChannelException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
new file mode 100644
index 0000000..459d85a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NonWritableChannelExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.NonWritableChannelException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NonWritableChannelException
+ */
+public class NonWritableChannelExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.NonWritableChannelException#NonWritableChannelException()}
+ */
+ public void test_Constructor() {
+ NonWritableChannelException e = new NonWritableChannelException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NonWritableChannelException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NonWritableChannelException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
new file mode 100644
index 0000000..d1c2d86
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetBoundExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.NotYetBoundException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetBoundException
+ */
+public class NotYetBoundExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.NotYetBoundException#NotYetBoundException()}
+ */
+ public void test_Constructor() {
+ NotYetBoundException e = new NotYetBoundException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NotYetBoundException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NotYetBoundException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
new file mode 100644
index 0000000..09e4c1c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/NotYetConnectedExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.NotYetConnectedException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for NotYetConnectedException
+ */
+public class NotYetConnectedExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.NotYetConnectedException#NotYetConnectedException()}
+ */
+ public void test_Constructor() {
+ NotYetConnectedException e = new NotYetConnectedException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new NotYetConnectedException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new NotYetConnectedException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
new file mode 100644
index 0000000..d06f807
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/OverlappingFileLockExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.OverlappingFileLockException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for OverlappingFileLockException
+ */
+public class OverlappingFileLockExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.OverlappingFileLockException#OverlappingFileLockException()}
+ */
+ public void test_Constructor() {
+ OverlappingFileLockException e = new OverlappingFileLockException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new OverlappingFileLockException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest
+ .verifyGolden(this, new OverlappingFileLockException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
new file mode 100644
index 0000000..53f19c4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/PipeTest.java
@@ -0,0 +1,59 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.NetPermission;
+import java.nio.channels.Pipe;
+import java.nio.channels.Pipe.SinkChannel;
+import java.nio.channels.Pipe.SourceChannel;
+import java.security.Permission;
+
+import junit.framework.TestCase;
+
+/*
+ * Tests for Pipe and its default implementation
+ */
+public class PipeTest extends TestCase {
+
+ /**
+ * @tests java.nio.channels.Pipe#open()
+ */
+ public void test_open() throws IOException{
+ Pipe pipe = Pipe.open();
+ assertNotNull(pipe);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe#sink()
+ */
+ public void test_sink() throws IOException {
+ Pipe pipe = Pipe.open();
+ SinkChannel sink = pipe.sink();
+ assertTrue(sink.isBlocking());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe#source()
+ */
+ public void test_source() throws IOException {
+ Pipe pipe = Pipe.open();
+ SourceChannel source = pipe.source();
+ assertTrue(source.isBlocking());
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
new file mode 100644
index 0000000..25b5f00
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectableChannelTest.java
@@ -0,0 +1,89 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.SelectorProvider;
+import junit.framework.TestCase;
+
+/*
+ * Tests for SelectableChannel
+ */
+public class SelectableChannelTest extends TestCase {
+
+ /**
+ * @tests SelectableChannel#register(Selector, int)
+ */
+ public void test_register_LSelectorI() throws IOException {
+ MockSelectableChannel msc = new MockSelectableChannel();
+ // Verify that calling register(Selector, int) leads to the method
+ // register(Selector, int, Object) being called with a null value
+ // for the third argument.
+ msc.register(Selector.open(), SelectionKey.OP_ACCEPT);
+ assertTrue(msc.isCalled);
+ }
+
+ private class MockSelectableChannel extends SelectableChannel {
+
+ private boolean isCalled = false;
+
+ public Object blockingLock() {
+ return null;
+ }
+
+ public SelectableChannel configureBlocking(boolean block)
+ throws IOException {
+ return null;
+ }
+
+ public boolean isBlocking() {
+ return false;
+ }
+
+ public boolean isRegistered() {
+ return false;
+ }
+
+ public SelectionKey keyFor(Selector sel) {
+ return null;
+ }
+
+ public SelectorProvider provider() {
+ return null;
+ }
+
+ public SelectionKey register(Selector sel, int ops, Object att)
+ throws ClosedChannelException {
+ if (null == att) {
+ isCalled = true;
+ }
+ return null;
+ }
+
+ public int validOps() {
+ return 0;
+ }
+
+ protected void implCloseChannel() throws IOException {
+ // empty
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
new file mode 100644
index 0000000..ed33752
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectionKeyTest.java
@@ -0,0 +1,321 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.CancelledKeyException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * Tests for SelectionKey and its default implementation
+ */
+public class SelectionKeyTest extends TestCase {
+
+ Selector selector;
+
+ SocketChannel sc;
+
+ SelectionKey selectionKey;
+
+ private static String LOCAL_ADDR = "127.0.0.1";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ selector = Selector.open();
+ sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
+ }
+
+ protected void tearDown() throws Exception {
+ selectionKey.cancel();
+ selectionKey = null;
+ selector.close();
+ selector = null;
+ super.tearDown();
+ }
+
+ static class MockSelectionKey extends SelectionKey {
+ private int interestOps;
+
+ MockSelectionKey(int ops) {
+ interestOps = ops;
+ }
+
+ public void cancel() {
+ // do nothing
+ }
+
+ public SelectableChannel channel() {
+ return null;
+ }
+
+ public int interestOps() {
+ return 0;
+ }
+
+ public SelectionKey interestOps(int operations) {
+ return null;
+ }
+
+ public boolean isValid() {
+ return true;
+ }
+
+ public int readyOps() {
+ return interestOps;
+ }
+
+ public Selector selector() {
+ return null;
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#attach(Object)
+ */
+ public void test_attach() {
+ MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ // no previous, return null
+ Object o = new Object();
+ Object check = mockSelectionKey.attach(o);
+ assertNull(check);
+
+ // null parameter is ok
+ check = mockSelectionKey.attach(null);
+ assertSame(o, check);
+
+ check = mockSelectionKey.attach(o);
+ assertNull(check);
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#attachment()
+ */
+ public void test_attachment() {
+ MockSelectionKey mockSelectionKey = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertNull(mockSelectionKey.attachment());
+ Object o = new Object();
+ mockSelectionKey.attach(o);
+ assertSame(o, mockSelectionKey.attachment());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#channel()
+ */
+ public void test_channel() {
+ assertSame(sc, selectionKey.channel());
+ // can be invoked even canceled
+ selectionKey.cancel();
+ assertSame(sc, selectionKey.channel());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#interestOps()
+ */
+ public void test_interestOps() {
+ assertEquals(SelectionKey.OP_CONNECT, selectionKey.interestOps());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#interestOps(int)
+ */
+ public void test_interestOpsI() {
+ selectionKey.interestOps(SelectionKey.OP_WRITE);
+ assertEquals(SelectionKey.OP_WRITE, selectionKey.interestOps());
+
+ try {
+ selectionKey.interestOps(SelectionKey.OP_ACCEPT);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ try {
+ selectionKey.interestOps(~sc.validOps());
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+ try {
+ selectionKey.interestOps(-1);
+ fail("should throw IAE.");
+ } catch (IllegalArgumentException ex) {
+ // expected;
+ }
+
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid() {
+ assertTrue(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_KeyCancelled() {
+ selectionKey.cancel();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_ChannelColsed() throws IOException {
+ sc.close();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isValid()
+ */
+ public void test_isValid_SelectorClosed() throws IOException {
+ selector.close();
+ assertFalse(selectionKey.isValid());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isAcceptable()
+ */
+ public void test_isAcceptable() throws IOException {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertTrue(mockSelectionKey1.isAcceptable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+ assertFalse(mockSelectionKey2.isAcceptable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isConnectable()
+ */
+ public void test_isConnectable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_CONNECT);
+ assertTrue(mockSelectionKey1.isConnectable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isConnectable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isReadable()
+ */
+ public void test_isReadable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_READ);
+ assertTrue(mockSelectionKey1.isReadable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isReadable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#isWritable()
+ */
+ public void test_isWritable() {
+ MockSelectionKey mockSelectionKey1 = new MockSelectionKey(SelectionKey.OP_WRITE);
+ assertTrue(mockSelectionKey1.isWritable());
+ MockSelectionKey mockSelectionKey2 = new MockSelectionKey(SelectionKey.OP_ACCEPT);
+ assertFalse(mockSelectionKey2.isWritable());
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#cancel()
+ */
+ public void test_cancel() {
+ selectionKey.cancel();
+ try {
+ selectionKey.isAcceptable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isConnectable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isReadable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ try {
+ selectionKey.isWritable();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.readyOps();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.interestOps(SelectionKey.OP_CONNECT);
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+
+ try {
+ selectionKey.interestOps();
+ fail("should throw CancelledKeyException.");
+ } catch (CancelledKeyException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#readyOps()
+ */
+ public void test_readyOps() throws IOException {
+ int port = Support_PortManager.getNextPort();
+ ServerSocket ss = new ServerSocket(port);
+ try {
+ sc.connect(new InetSocketAddress(LOCAL_ADDR, port));
+ assertEquals(0, selectionKey.readyOps());
+ assertFalse(selectionKey.isConnectable());
+ selector.select();
+ assertEquals(SelectionKey.OP_CONNECT, selectionKey.readyOps());
+ } finally {
+ ss.close();
+ ss = null;
+ }
+
+ }
+
+ /**
+ * @tests java.nio.channels.SelectionKey#selector()
+ */
+ public void test_selector() {
+ assertSame(selector, selectionKey.selector());
+ selectionKey.cancel();
+ assertSame(selector, selectionKey.selector());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
new file mode 100644
index 0000000..3617230
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SelectorTest.java
@@ -0,0 +1,685 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+import java.net.SocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.Set;
+import junit.framework.TestCase;
+
+/*
+ * Tests for Selector and its default implementation
+ */
+public class SelectorTest extends TestCase {
+ private static final int WAIT_TIME = 100;
+
+ private SocketAddress localAddress;
+
+ private Selector selector;
+
+ private ServerSocketChannel ssc;
+
+ private enum SelectType {
+ NULL, TIMEOUT, NOW
+ };
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ ServerSocket ss = ssc.socket();
+ ss.bind(null);
+ localAddress = ss.getLocalSocketAddress();
+ selector = Selector.open();
+ }
+
+ protected void tearDown() throws Exception {
+ try {
+ ssc.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ try {
+ selector.close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ super.tearDown();
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#open()
+ */
+ public void test_open() throws IOException {
+ assertNotNull(selector);
+ }
+
+ /**
+ * @tests Selector#isOpen()
+ */
+ public void test_isOpen() throws IOException {
+ assertTrue(selector.isOpen());
+ selector.close();
+ assertFalse(selector.isOpen());
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#provider()
+ */
+ public void test_provider() throws IOException {
+ // should be system default provider
+ assertNotNull(selector.provider());
+ assertSame(SelectorProvider.provider(), selector.provider());
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#keys()
+ */
+ public void test_keys() throws IOException {
+ SelectionKey key = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+ Set<SelectionKey> keySet = selector.keys();
+ Set<SelectionKey> keySet2 = selector.keys();
+
+ assertSame(keySet, keySet2);
+ assertEquals(1,keySet.size());
+ SelectionKey key2 = keySet.iterator().next();
+ assertEquals(key,key2);
+
+ // Any attempt to modify keys will cause UnsupportedOperationException
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ SelectionKey key3 = sc.register(selector, SelectionKey.OP_READ);
+ try {
+ keySet2.add(key3);
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ keySet2.remove(key3);
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ try {
+ keySet2.clear();
+ fail("should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ selector.close();
+ try {
+ selector.keys();
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#keys()
+ */
+ public void test_selectedKeys() throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ ssc.register(selector, SelectionKey.OP_ACCEPT);
+ try {
+ int count = 0;
+ sc.connect(localAddress);
+ count = blockingSelect(SelectType.NULL, 0);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ Set<SelectionKey> selectedKeys2 = selector.selectedKeys();
+ assertSame(selectedKeys, selectedKeys2);
+
+ assertEquals(1, selectedKeys.size());
+ assertEquals(ssc.keyFor(selector), selectedKeys.iterator().next());
+ // add one key into selectedKeys
+ try {
+ selectedKeys.add(ssc.keyFor(selector));
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+
+ // no exception should be thrown
+ selectedKeys.clear();
+
+ Set<SelectionKey> selectedKeys3 = selector.selectedKeys();
+ assertSame(selectedKeys, selectedKeys3);
+
+ ssc.keyFor(selector).cancel();
+ assertEquals(0, selectedKeys.size());
+ selector.close();
+ try {
+ selector.selectedKeys();
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ } finally {
+ sc.close();
+ }
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#selectNow()
+ */
+ public void test_selectNow() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.NOW, 0);
+ assert_select_OP_CONNECT(SelectType.NOW, 0);
+ assert_select_OP_READ(SelectType.NOW, 0);
+ assert_select_OP_WRITE(SelectType.NOW, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#selectNow()
+ */
+ public void test_selectNow_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.NOW, 0);
+ }
+
+ /**
+ * @test java.nio.channels.Selector#selectNow()
+ */
+ public void test_selectNow_Timeout() throws IOException {
+ // make sure selectNow doesn't block
+ selector.selectNow();
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select()
+ */
+ public void test_select() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.NULL, 0);
+ assert_select_OP_CONNECT(SelectType.NULL, 0);
+ assert_select_OP_READ(SelectType.NULL, 0);
+ assert_select_OP_WRITE(SelectType.NULL, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select()
+ */
+ public void test_select_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.NULL, 0);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ() throws IOException {
+ assert_select_OP_ACCEPT(SelectType.TIMEOUT, 0);
+ assert_select_OP_CONNECT(SelectType.TIMEOUT, 0);
+ assert_select_OP_READ(SelectType.TIMEOUT, 0);
+ assert_select_OP_WRITE(SelectType.TIMEOUT, 0);
+
+ assert_select_OP_ACCEPT(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_CONNECT(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_READ(SelectType.TIMEOUT, WAIT_TIME);
+ assert_select_OP_WRITE(SelectType.TIMEOUT, WAIT_TIME);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ_SelectorClosed() throws IOException {
+ assert_select_SelectorClosed(SelectType.TIMEOUT, 0);
+ selector = Selector.open();
+ assert_select_SelectorClosed(SelectType.TIMEOUT, WAIT_TIME);
+ }
+
+ /**
+ * @tests java.nio.channel.Selector#select(long)
+ */
+ public void test_selectJ_Exception() throws IOException {
+ try {
+ selector.select(-1);
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.nio.channels.Selector#select(long)
+ */
+ public void test_selectJ_Timeout() throws IOException {
+ // make sure select(timeout) doesn't block
+ selector.select(WAIT_TIME);
+ }
+
+ /**
+ * @test java.nio.channels.Selector#select(long)
+ */
+ public void test_selectJ_Empty_Keys() throws IOException {
+ // regression test, see HARMONY-3888.
+ // make sure select(long) does wait for specified amount of
+ // time if keys.size() == 0 (initial state of selector).
+
+ final long SELECT_TIMEOUT_MS = 2000;
+
+ long t0 = System.nanoTime();
+ selector.select(SELECT_TIMEOUT_MS);
+ long t1 = System.nanoTime();
+
+ long waitMs = (t1 - t0) / 1000L / 1000L;
+ assertTrue(waitMs >= SELECT_TIMEOUT_MS);
+ assertTrue(waitMs < 5*SELECT_TIMEOUT_MS);
+ }
+
+ /**
+ * @tests java.nio.channels.Selector#wakeup()
+ */
+ public void test_wakeup() throws IOException {
+ /*
+ * make sure the test does not block on select
+ */
+ selector.wakeup();
+ selectOnce(SelectType.NULL, 0);
+ selector.wakeup();
+ selectOnce(SelectType.TIMEOUT, 0);
+
+ // try to wakeup select. The invocation sequence of wakeup and select
+ // doesn't affect test result.
+ new Thread() {
+ public void run() {
+
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ selector.wakeup();
+ }
+ }.start();
+ selectOnce(SelectType.NULL, 0);
+
+ // try to wakeup select. The invocation sequence of wakeup and select
+ // doesn't affect test result.
+ new Thread() {
+ public void run() {
+
+ try {
+ Thread.sleep(WAIT_TIME);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ selector.wakeup();
+ }
+ }.start();
+ selectOnce(SelectType.TIMEOUT, 0);
+ }
+
+ public void test_keySetViewsModifications() throws IOException {
+ Set<SelectionKey> keys = selector.keys();
+
+ SelectionKey key1 = ssc.register(selector, SelectionKey.OP_ACCEPT);
+
+ assertTrue(keys.contains(key1));
+
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ SelectionKey key2 = sc.register(selector, SelectionKey.OP_READ);
+
+ assertTrue(keys.contains(key1));
+ assertTrue(keys.contains(key2));
+
+ key1.cancel();
+ assertTrue(keys.contains(key1));
+
+ selector.selectNow();
+ assertFalse(keys.contains(key1));
+ assertTrue(keys.contains(key2));
+ }
+
+ /**
+ * This test cancels a key while selecting to verify that the cancelled
+ * key set is processed both before and after the call to the underlying
+ * operating system.
+ */
+ public void test_cancelledKeys() throws Exception {
+ final AtomicReference<Throwable> failure = new AtomicReference<Throwable>();
+ final AtomicBoolean complete = new AtomicBoolean();
+
+ final Pipe pipe = Pipe.open();
+ pipe.source().configureBlocking(false);
+ final SelectionKey key = pipe.source().register(selector, SelectionKey.OP_READ);
+
+ Thread thread = new Thread() {
+ public void run() {
+ try {
+ // make sure to call key.cancel() while the main thread is selecting
+ Thread.sleep(500);
+ key.cancel();
+ assertFalse(key.isValid());
+ pipe.sink().write(ByteBuffer.allocate(4)); // unblock select()
+ } catch (Throwable e) {
+ failure.set(e);
+ } finally {
+ complete.set(true);
+ }
+ }
+ };
+ assertTrue(key.isValid());
+
+ thread.start();
+ do {
+ assertEquals(0, selector.select(5000)); // blocks
+ assertEquals(0, selector.selectedKeys().size());
+ } while (!complete.get()); // avoid spurious interrupts
+ assertFalse(key.isValid());
+
+ thread.join();
+ assertNull(failure.get());
+ }
+
+ public void testOpChange() throws Exception {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_CONNECT);
+ try {
+ sc.connect(localAddress);
+ int count = blockingSelect(SelectType.TIMEOUT, 100);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_CONNECT, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(SelectType.TIMEOUT, 100);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ sc.finishConnect();
+
+ // same selector, but op is changed
+ SelectionKey key1 = sc.register(selector, SelectionKey.OP_WRITE);
+ assertEquals(key, key1);
+ count = blockingSelect(SelectType.TIMEOUT, 100);
+ assertEquals(1, count);
+ selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ key = selectedKeys.iterator().next();
+ assertEquals(key, key1);
+ assertEquals(SelectionKey.OP_WRITE, key.readyOps());
+
+ selectedKeys.clear();
+ } finally {
+ try {
+ ssc.accept().close();
+ } catch (Exception e) {
+ // do nothing
+ }
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+
+ public void test_nonBlockingConnect() throws IOException {
+ SocketChannel channel = null;
+ try {
+ channel = SocketChannel.open();
+ channel.configureBlocking(false);
+ Selector selector = Selector.open();
+ channel.register(selector, SelectionKey.OP_CONNECT);
+ channel.connect(localAddress);
+ channel.finishConnect();
+ selector.select();
+ assertEquals(0, selector.selectedKeys().size());
+ } finally {
+ channel.close();
+ }
+ }
+
+ private void assert_select_SelectorClosed(SelectType type, int timeout)
+ throws IOException {
+ // selector is closed
+ selector.close();
+ try {
+ selectOnce(type, timeout);
+ fail("should throw ClosedSelectorException");
+ } catch (ClosedSelectorException e) {
+ // expected
+ }
+ }
+
+ private void assert_select_OP_ACCEPT(SelectType type, int timeout)
+ throws IOException, ClosedChannelException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ try {
+ ssc.register(selector, SelectionKey.OP_ACCEPT);
+ sc.connect(localAddress);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(ssc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_ACCEPT, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0,count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ client = ssc.accept();
+ selectedKeys.clear();
+ } finally {
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ if (null != client) {
+ client.close();
+ }
+ }
+ ssc.keyFor(selector).cancel();
+ }
+
+ private void assert_select_OP_CONNECT(SelectType type, int timeout)
+ throws IOException, ClosedChannelException {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_CONNECT);
+ try {
+ sc.connect(localAddress);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_CONNECT, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ sc.finishConnect();
+ selectedKeys.clear();
+ } finally {
+ try {
+ ssc.accept().close();
+ } catch (Exception e) {
+ // do nothing
+ }
+
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+
+ private void assert_select_OP_READ(SelectType type, int timeout)
+ throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ SocketChannel sc2 = SocketChannel.open();
+ SocketChannel client2 = null;
+ try {
+ ssc.configureBlocking(true);
+ sc.connect(localAddress);
+ client = ssc.accept();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_READ);
+ client.configureBlocking(true);
+
+ sc2.connect(localAddress);
+ client2 = ssc.accept();
+ sc2.configureBlocking(false);
+ sc2.register(selector, SelectionKey.OP_READ);
+ client2.configureBlocking(true);
+
+ client.write(ByteBuffer.wrap("a".getBytes()));
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_READ, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+
+ sc.read(ByteBuffer.allocate(8));
+
+ // the second SocketChannel should be selected this time
+ client2.write(ByteBuffer.wrap("a".getBytes()));
+ count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ // selectedKeys still includes the key of sc, because the key of sc
+ // is not removed last time.
+ selectedKeys = selector.selectedKeys();
+ assertEquals(2, selectedKeys.size());
+ } finally {
+ if (null != client) {
+ try {
+ client.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ if (null != client2) {
+ try {
+ client2.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ try {
+ sc.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ try {
+ sc2.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ ssc.configureBlocking(false);
+ }
+ }
+
+ private void assert_select_OP_WRITE(SelectType type, int timeout)
+ throws IOException {
+ SocketChannel sc = SocketChannel.open();
+ SocketChannel client = null;
+ try {
+ sc.connect(localAddress);
+ ssc.configureBlocking(true);
+ client = ssc.accept();
+ sc.configureBlocking(false);
+ sc.register(selector, SelectionKey.OP_WRITE);
+ int count = blockingSelect(type, timeout);
+ assertEquals(1, count);
+ Set<SelectionKey> selectedKeys = selector.selectedKeys();
+ assertEquals(1, selectedKeys.size());
+ SelectionKey key = selectedKeys.iterator().next();
+ assertEquals(sc.keyFor(selector), key);
+ assertEquals(SelectionKey.OP_WRITE, key.readyOps());
+ // select again, it should return 0
+ count = selectOnce(type, timeout);
+ assertEquals(0, count);
+ // but selectedKeys remains the same as previous
+ assertSame(selectedKeys, selector.selectedKeys());
+ } finally {
+ if (null != client) {
+ client.close();
+ }
+ try {
+ sc.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ ssc.configureBlocking(false);
+ }
+ }
+
+ private int blockingSelect(SelectType type, int timeout) throws IOException {
+ int ret = 0;
+ do {
+ ret = selectOnce(type, timeout);
+ if (ret > 0) {
+ return ret;
+ }
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ // ignore
+ }
+ } while (true);
+ }
+
+ private int selectOnce(SelectType type, int timeout) throws IOException {
+ int ret = 0;
+ switch (type) {
+ case NULL:
+ ret = selector.select();
+ break;
+ case TIMEOUT:
+ ret = selector.select(timeout);
+ break;
+ case NOW:
+ ret = selector.selectNow();
+ break;
+ }
+ return ret;
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
new file mode 100644
index 0000000..fdbbc48
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/ServerSocketChannelTest.java
@@ -0,0 +1,682 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NotYetBoundException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/*
+ * test for ServerSocketChannel
+ */
+public class ServerSocketChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private static final int CAPACITY_64KB = 65536;
+
+ private static final int TIME_UNIT = 200;
+
+ private InetSocketAddress localAddr1;
+
+ private ServerSocketChannel serverChannel;
+
+ private SocketChannel clientChannel;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.localAddr1 = new InetSocketAddress(
+ "127.0.0.1", Support_PortManager
+ .getNextPort());
+ this.serverChannel = ServerSocketChannel.open();
+ this.clientChannel = SocketChannel.open();
+ }
+
+ protected void tearDown() throws Exception {
+ if (null != this.serverChannel) {
+ try {
+ this.serverChannel.close();
+ } catch (Exception e) {
+ //ignore
+ }
+
+ }
+ if (null != this.clientChannel) {
+ try {
+ this.clientChannel.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ super.tearDown();
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockServerSocketChannel testMSChnlnull = new MockServerSocketChannel(
+ null);
+ MockServerSocketChannel testMSChnl = new MockServerSocketChannel(
+ SelectorProvider.provider());
+ assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnl.validOps());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnull.validOps());
+
+ }
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.open()'
+ */
+ public void testOpen() {
+ MockServerSocketChannel testMSChnl = new MockServerSocketChannel(null);
+ MockServerSocketChannel testMSChnlnotnull = new MockServerSocketChannel(
+ SelectorProvider.provider());
+ assertEquals(SelectionKey.OP_ACCEPT, testMSChnlnotnull.validOps());
+ assertNull(testMSChnl.provider());
+ assertNotNull(testMSChnlnotnull.provider());
+ assertNotNull(this.serverChannel.provider());
+ assertEquals(testMSChnlnotnull.provider(), this.serverChannel
+ .provider());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for socket()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.socket()'
+ */
+ public void testSocket_Block_BeforeClose() throws Exception {
+ assertTrue(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertFalse(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+
+ // socket close makes the channel close
+ s1.close();
+ assertFalse(this.serverChannel.isOpen());
+
+ }
+
+ public void testSocket_NonBlock_BeforeClose() throws Exception {
+ assertTrue(this.serverChannel.isOpen());
+ this.serverChannel.configureBlocking(false);
+ ServerSocket s1 = this.serverChannel.socket();
+ assertFalse(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+
+ // socket close makes the channel close
+ s1.close();
+ assertFalse(this.serverChannel.isOpen());
+
+ }
+
+ public void testSocket_Block_Closed() throws Exception {
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertTrue(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_Closed() throws Exception {
+ this.serverChannel.configureBlocking(false);
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isBlocking());
+ assertFalse(this.serverChannel.isOpen());
+ ServerSocket s1 = this.serverChannel.socket();
+ assertTrue(s1.isClosed());
+ assertSocketNotAccepted(s1);
+ ServerSocket s2 = this.serverChannel.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ private void assertSocketNotAccepted(ServerSocket s) throws IOException {
+ assertFalse(s.isBound());
+ assertNull(s.getInetAddress());
+ assertEquals(-1, s.getLocalPort());
+ assertNull(s.getLocalSocketAddress());
+ try {
+ assertEquals(0, s.getSoTimeout());
+ } catch (IOException expected) {
+ // Android doesn't cache the timeout, so the getsockopt(2) fails and throws.
+ }
+ }
+
+ public void testChannelBasicStatus() {
+ ServerSocket gotSocket = this.serverChannel.socket();
+ assertFalse(gotSocket.isClosed());
+ assertTrue(this.serverChannel.isBlocking());
+ assertFalse(this.serverChannel.isRegistered());
+ assertEquals(SelectionKey.OP_ACCEPT, this.serverChannel.validOps());
+ assertEquals(SelectorProvider.provider(), this.serverChannel.provider());
+ }
+
+ // -------------------------------------------------------------------
+ // Test for accept()
+ // -------------------------------------------------------------------
+
+ /*
+ * Test method for 'java.nio.channels.ServerSocketChannel.accept()'
+ */
+
+ public void testAccept_Block_NotYetBound() throws IOException {
+ assertTrue(this.serverChannel.isOpen());
+ assertTrue(this.serverChannel.isBlocking());
+ try {
+ this.serverChannel.accept();
+ fail("Should throw NotYetBoundException");
+ } catch (NotYetBoundException e) {
+ // correct
+ }
+ }
+
+ public void testAccept_NonBlock_NotYetBound() throws IOException {
+ assertTrue(this.serverChannel.isOpen());
+ this.serverChannel.configureBlocking(false);
+ try {
+ this.serverChannel.accept();
+ fail("Should throw NotYetBoundException");
+ } catch (NotYetBoundException e) {
+ // correct
+ }
+ }
+
+ public void testAccept_ClosedChannel() throws Exception {
+ this.serverChannel.close();
+ assertFalse(this.serverChannel.isOpen());
+ try {
+ this.serverChannel.accept();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ public void testAccept_Block_NoConnect() throws IOException {
+ assertTrue(this.serverChannel.isBlocking());
+ ServerSocket gotSocket = this.serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ // blocking mode , will block and wait for ever...
+ // so must close the server channel with another thread.
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ ServerSocketChannelTest.this.serverChannel.close();
+ } catch (Exception e) {
+ fail("Fail to close the server channel because of"
+ + e.getClass().getName());
+ }
+ }
+ }.start();
+ try {
+ this.serverChannel.accept();
+ fail("Should throw a AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // OK.
+ }
+ }
+
+ public void testAccept_NonBlock_NoConnect() throws IOException {
+ ServerSocket gotSocket = this.serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ this.serverChannel.configureBlocking(false);
+ // non-blocking mode , will immediately return
+ assertNull(this.serverChannel.accept());
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_Blocking_RealData() throws IOException {
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ buf.put((byte) i);
+ }
+ clientChannel.connect(localAddr1);
+ Socket serverSocket = serverChannel.accept().socket();
+ InputStream in = serverSocket.getInputStream();
+ buf.flip();
+ clientChannel.write(buf);
+ clientChannel.close();
+ assertReadResult(in,CAPACITY_NORMAL);
+ }
+
+ /**
+ * Asserts read content. The read content should contain <code>size</code>
+ * bytes, and the value should be a sequence from 0 to size-1
+ * ([0,1,...size-1]). Otherwise, the method throws Exception.
+ *
+ */
+ private void assertReadResult(InputStream in, int size) throws IOException{
+ byte[] readContent = new byte[size + 1];
+ int count = 0;
+ int total = 0;
+ while ((count = in.read(readContent, total, size + 1 - total)) != -1) {
+ total = total + count;
+ }
+ assertEquals(size, total);
+ for (int i = 0; i < size; i++) {
+ assertEquals((byte) i, readContent[i]);
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_NonBlocking_RealData() throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ Socket serverSocket = serverChannel.accept().socket();
+ InputStream in = serverSocket.getInputStream();
+ clientChannel.write(buf);
+ clientChannel.close();
+ assertReadResult(in,CAPACITY_NORMAL);
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_Blocking_RealData() throws IOException {
+ assertTrue(serverChannel.isBlocking());
+ ServerSocket serverSocket = serverChannel.socket();
+ serverSocket.bind(localAddr1);
+
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ OutputStream out = socket.getOutputStream();
+ out.write(writeContent);
+ out.flush();
+ socket.close();
+ assertWriteResult(CAPACITY_NORMAL);
+ }
+
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_NonBlocking_RealData() throws Exception {
+ serverChannel.configureBlocking(false);
+ ServerSocket serverSocket = serverChannel.socket();
+ serverSocket.bind(localAddr1);
+
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket clientSocket = serverChannel.accept().socket();
+ OutputStream out = clientSocket.getOutputStream();
+ out.write(writeContent);
+ clientSocket.close();
+ assertWriteResult(CAPACITY_NORMAL);
+ }
+
+ /**
+ * @throws InterruptedException
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_LByteBuffer_Blocking_ReadWriteRealLargeData()
+ throws IOException, InterruptedException {
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf);
+ writeThread.start();
+ Socket socket = serverChannel.accept().socket();
+ InputStream in = socket.getInputStream();
+ assertReadResult(in,CAPACITY_64KB);
+ writeThread.join();
+ // check if the thread threw any exceptions
+ if (writeThread.exception != null) {
+ throw writeThread.exception;
+ }
+ }
+
+ class WriteChannelThread extends Thread {
+ SocketChannel channel;
+ ByteBuffer buffer;
+ IOException exception;
+
+ public WriteChannelThread(SocketChannel channel, ByteBuffer buffer) {
+ this.channel = channel;
+ this.buffer = buffer;
+ }
+
+ public void run() {
+ try {
+ channel.write(buffer);
+ channel.close();
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_read_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ ByteBuffer buf = ByteBuffer.allocate(CAPACITY_64KB);
+ for (int i = 0; i < CAPACITY_64KB; i++) {
+ buf.put((byte) i);
+ }
+ buf.flip();
+ clientChannel.connect(localAddr1);
+ WriteChannelThread writeThread = new WriteChannelThread(clientChannel, buf);
+ writeThread.start();
+ Socket socket = serverChannel.accept().socket();
+ InputStream in = socket.getInputStream();
+ assertReadResult(in,CAPACITY_64KB);
+ writeThread.join();
+ // check if the thread threw any exceptions
+ if (writeThread.exception != null) {
+ throw writeThread.exception;
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_LByteBuffer_NonBlocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.configureBlocking(false);
+ serverChannel.socket().bind(localAddr1);
+ byte[] writeContent = new byte[CAPACITY_64KB];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent);
+ writeThread.start();
+ assertWriteResult(CAPACITY_64KB);
+ writeThread.join();
+ // check if the thread threw any exceptions
+ if (writeThread.exception != null) {
+ throw writeThread.exception;
+ }
+ }
+
+ class WriteSocketThread extends Thread {
+ Socket socket;
+ byte[] buffer;
+ IOException exception;
+
+ public WriteSocketThread(Socket socket, byte[] buffer) {
+ this.socket = socket;
+ this.buffer = buffer;
+ }
+
+ public void run() {
+ try {
+ OutputStream out = socket.getOutputStream();
+ out.write(buffer);
+ socket.close();
+ } catch (IOException e) {
+ exception = e;
+ }
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#accept().socket()
+ */
+ public void test_write_LByteBuffer_Blocking_ReadWriteRealLargeData()
+ throws Exception {
+ serverChannel.socket().bind(localAddr1);
+ byte[] writeContent = new byte[CAPACITY_64KB];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ clientChannel.connect(localAddr1);
+ Socket socket = serverChannel.accept().socket();
+ WriteSocketThread writeThread = new WriteSocketThread(socket, writeContent);
+ writeThread.start();
+ assertWriteResult(CAPACITY_64KB);
+ writeThread.join();
+ // check if the thread threw any exceptions
+ if (writeThread.exception != null) {
+ throw writeThread.exception;
+ }
+ }
+
+ /**
+ * Uses SocketChannel.read(ByteBuffer) to verify write result.
+ */
+ private void assertWriteResult(int size) throws IOException{
+ ByteBuffer buf = ByteBuffer.allocate(size + 1);
+ int count = 0;
+ int total = 0;
+ long beginTime = System.currentTimeMillis();
+ while ((count = clientChannel.read(buf)) != -1) {
+ total = total + count;
+ // 10s timeout to avoid dead loop
+ if (System.currentTimeMillis() - beginTime > 10000){
+ break;
+ }
+ }
+ assertEquals(total, size);
+ buf.flip();
+ for (int i = 0; i < count; i++) {
+ assertEquals((byte) i, buf.get(i));
+ }
+ }
+
+ /**
+ * @tests ServerSocketChannel#socket().getSoTimeout()
+ */
+ public void test_accept_SOTIMEOUT() throws IOException {
+ // regression test for Harmony-707
+ final int SO_TIMEOUT = 10;
+ ServerSocketChannel sc = ServerSocketChannel.open();
+ try {
+ ServerSocket ss = sc.socket();
+ ss.bind(localAddr1);
+ sc.configureBlocking(false);
+ ss.setSoTimeout(SO_TIMEOUT);
+ SocketChannel client = sc.accept();
+ // non blocking mode, returns null since there are no pending connections.
+ assertNull(client);
+ int soTimeout = ss.getSoTimeout();
+ // Harmony fails here.
+ assertEquals(SO_TIMEOUT, soTimeout);
+ } finally {
+ sc.close();
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Blocking_NotBound() throws IOException {
+ // regression test for Harmony-748
+ ServerSocket gotSocket = serverChannel.socket();
+ serverChannel.configureBlocking(true);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Nonblocking_NotBound() throws IOException {
+ // regression test for Harmony-748
+ ServerSocket gotSocket = serverChannel.socket();
+ serverChannel.configureBlocking(false);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Nonblocking_Bound() throws IOException {
+ // regression test for Harmony-748
+ serverChannel.configureBlocking(false);
+ ServerSocket gotSocket = serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ try {
+ gotSocket.accept();
+ fail("Should throw an IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw a ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests ServerSocket#socket().accept()
+ */
+ public void test_socket_accept_Blocking_Bound() throws IOException {
+ // regression test for Harmony-748
+ serverChannel.configureBlocking(true);
+ ServerSocket gotSocket = serverChannel.socket();
+ gotSocket.bind(localAddr1);
+ serverChannel.close();
+ try {
+ gotSocket.accept();
+ fail("Should throw a ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+ /**
+ * Regression test for HARMONY-4961
+ */
+ public void test_socket_getLocalPort() throws IOException {
+ serverChannel.socket().bind(localAddr1);
+ clientChannel.connect(localAddr1);
+ SocketChannel myChannel = serverChannel.accept();
+ int port = myChannel.socket().getLocalPort();
+ assertEquals(localAddr1.getPort(), port);
+ myChannel.close();
+ clientChannel.close();
+ serverChannel.close();
+ }
+
+ /**
+ * Regression test for HARMONY-6375
+ */
+ public void test_accept_configureBlocking() throws Exception {
+ InetSocketAddress localAddr = new InetSocketAddress("localhost", 0);
+ serverChannel.socket().bind(localAddr);
+
+ // configure the channel non-blocking
+ // when it is accepting in main thread
+ new Thread() {
+ public void run() {
+ try {
+ Thread.sleep(TIME_UNIT);
+ serverChannel.configureBlocking(false);
+ serverChannel.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+
+ try {
+ serverChannel.accept();
+ fail("should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // expected
+ }
+ serverChannel.close();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
new file mode 100644
index 0000000..9e96fad
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SinkChannelTest.java
@@ -0,0 +1,505 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for Pipe.SinkChannel class
+ */
+public class SinkChannelTest extends TestCase {
+
+ private static final int BUFFER_SIZE = 5;
+
+ private static final String ISO8859_1 = "ISO8859-1";
+
+ private Pipe pipe;
+
+ private Pipe.SinkChannel sink;
+
+ private Pipe.SourceChannel source;
+
+ private ByteBuffer buffer;
+
+ private ByteBuffer positionedBuffer;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+ positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+ positionedBuffer.position(BUFFER_SIZE);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#validOps()
+ */
+ public void test_validOps() {
+ assertEquals(SelectionKey.OP_WRITE, sink.validOps());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ int oldPosition;
+ int currentPosition;
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ for (ByteBuffer buf : bufArray) {
+ buf.mark();
+ oldPosition = buf.position();
+ sink.write(buf);
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count > 0) {
+ totalCount += count;
+ }
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ currentPosition = buf.position();
+ assertEquals(BUFFER_SIZE, currentPosition - oldPosition);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ buf.reset();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_mutliThread() throws IOException,
+ InterruptedException {
+ final int THREAD_NUM = 20;
+ final byte[] strbytes = "bytes".getBytes(ISO8859_1);
+ Thread[] thread = new Thread[THREAD_NUM];
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i] = new Thread() {
+ public void run() {
+ try {
+ sink.write(ByteBuffer.wrap(strbytes));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i].start();
+ }
+ for (int i = 0; i < THREAD_NUM; i++) {
+ thread[i].join();
+ }
+ ByteBuffer readBuf = ByteBuffer.allocate(THREAD_NUM * BUFFER_SIZE);
+
+ long totalCount = 0;
+ do {
+ long count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != (THREAD_NUM * BUFFER_SIZE));
+
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < THREAD_NUM; i++) {
+ buf.append("bytes");
+ }
+ String readString = buf.toString();
+ assertEquals(readString, new String(readBuf.array(), ISO8859_1));
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer)
+ */
+ public void test_write_LByteBuffer_Exception() throws IOException {
+ // write null ByteBuffer
+ ByteBuffer nullBuf = null;
+ try {
+ sink.write(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void test_write_LByteBuffer_SourceClosed() throws IOException {
+ source.close();
+ try {
+ int written = sink.write(buffer);
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ public void test_write_LByteBuffer_SinkClosed() throws IOException {
+ sink.close();
+ try {
+ sink.write(buffer);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ sink.write(bufArray);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ for (int j = 0; j < bufArray.length; ++j) {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ }
+ assertEquals(BUFFER_SIZE, buffer.position());
+ assertEquals(10, positionedBuffer.position());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer_Exception() throws IOException {
+ // write null ByteBuffer[]
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { buffer, nullBuf };
+ try {
+ sink.write(nullBufArray);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void test_write_$LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ source.close();
+ try {
+ long written = sink.write(bufArray);
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[])
+ */
+ public void test_write_$LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ sink.close();
+ try {
+ sink.write(bufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ sink.write(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ // write ByteBuffer[] contains null element
+ try {
+ sink.write(nullBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SinkChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_write_$LByteBufferII() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ positionedBuffer.position(BUFFER_SIZE);
+ sink.write(bufArray, 1, 1);
+ // if sink and source both are blocking mode, source only needs read
+ // once to get what sink write.
+ boolean isBlocking = sinkBlockingMode[i] && sourceBlockingMode[i];
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ int totalCount = 0;
+ do {
+ int count = source.read(readBuf);
+ if (count < 0) {
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != BUFFER_SIZE && !isBlocking);
+ assertEquals("bytes", new String(readBuf.array(), ISO8859_1));
+ assertEquals(10, positionedBuffer.position());
+ }
+ }
+
+ public void test_write_$LByteBufferII_Exception() throws IOException {
+ try {
+ sink.write(null, 0, 1);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ sink.write(new ByteBuffer[2], 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ try {
+ sink.write(nullBufArray, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ try {
+ sink.write(nullBufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray = { buffer, nullBuf };
+ try {
+ sink.write(bufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ public void test_write_$LByteBufferII_SourceClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ source.close();
+
+ try {
+ long written = sink.write(bufArray, 0, 1);
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ public void test_write_$LByteBufferII_SinkClosed() throws IOException {
+ ByteBuffer[] bufArray = { buffer };
+ sink.close();
+ try {
+ sink.write(bufArray, 0, 1);
+ fail();
+ } catch (ClosedChannelException expected) {
+ }
+
+ try {
+ sink.write(null, 0, 1);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ sink.write(new ByteBuffer[2], 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ // write ByteBuffer[] contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray = { nullBuf };
+ try {
+ sink.write(nullBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ // illegal array index
+ try {
+ sink.write(nullBufArray, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray2 = { buffer, nullBuf };
+ // illegal array index
+ try {
+ sink.write(bufArray2, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ sink.write(bufArray2, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ public void test_close() throws IOException {
+ sink.close();
+ assertFalse(sink.isOpen());
+ }
+
+ public void test_socketChannel_read_close() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sc = SocketChannel.open();
+ ByteBuffer buf = null;
+ try{
+ sc.write(buf);
+ fail("should throw NPE");
+ }catch (NullPointerException e){
+ // expected
+ }
+ sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sock = ssc.accept();
+ ssc.close();
+ sc.close();
+ try{
+ sc.write(buf);
+ fail("should throw NPE");
+ }catch (NullPointerException e){
+ // expected
+ }
+ sock.close();
+ }
+
+ public void test_socketChannel_read_write() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(new InetSocketAddress(InetAddress.getLocalHost(),49999));
+ SocketChannel sock = ssc.accept();
+ ByteBuffer[] buf = {ByteBuffer.allocate(10),null};
+ try {
+ sc.write(buf,0,2);
+ fail("should throw NPE");
+ } catch (NullPointerException expected) {
+ }
+ ssc.close();
+ sc.close();
+ ByteBuffer target = ByteBuffer.allocate(10);
+ assertEquals(-1, sock.read(target));
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
new file mode 100644
index 0000000..7325ba1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SocketChannelTest.java
@@ -0,0 +1,3628 @@
+/*
+ * 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.BindException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.SocketException;
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyConnectedException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.ConnectionPendingException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.NoConnectionPendingException;
+import java.nio.channels.NotYetConnectedException;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+import tests.support.Support_PortManager;
+
+/**
+ * Tests for SocketChannel and its default implementation.
+ */
+public class SocketChannelTest extends TestCase {
+
+ private static final int CAPACITY_NORMAL = 200;
+
+ private InetSocketAddress localAddr1;
+
+ private InetSocketAddress localAddr2;
+
+ private SocketChannel channel1;
+
+ private SocketChannel channel2;
+
+ private ServerSocket server1;
+
+ private ServerSocket server2;
+
+ private final static int TIMEOUT = 60000;
+
+ private final static int EOF = -1;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.localAddr1 = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ this.localAddr2 = new InetSocketAddress("127.0.0.1",
+ Support_PortManager.getNextPort());
+ this.channel1 = SocketChannel.open();
+ this.channel2 = SocketChannel.open();
+ this.server1 = new ServerSocket(localAddr1.getPort());
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (null != this.channel1) {
+ try {
+ this.channel1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.channel2) {
+ try {
+ this.channel2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.server1) {
+ try {
+ this.server1.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ if (null != this.server2) {
+ try {
+ this.server2.close();
+ } catch (Exception e) {
+ //ignore
+ }
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // Test for methods in abstract class.
+ // -------------------------------------------------------------------
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.validOps()'
+ */
+ public void testValidOps() {
+ MockSocketChannel testMSChannel = new MockSocketChannel(null);
+ assertEquals(13, this.channel1.validOps());
+ assertEquals(13, testMSChannel.validOps());
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.open()'
+ */
+ public void testOpen() throws IOException {
+ java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+ buf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ MockSocketChannel testMSChannel = new MockSocketChannel(null);
+ MockSocketChannel testMSChannelnotnull = new MockSocketChannel(
+ SelectorProvider.provider());
+ assertNull(testMSChannel.provider());
+ assertNotNull(testMSChannelnotnull.provider());
+ assertNotNull(this.channel1);
+ assertEquals(this.channel1.provider(), testMSChannelnotnull.provider());
+ try {
+ this.channel1.write(buf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.open(SocketAddress)'
+ */
+ public void testOpenSocketAddress_Null() throws IOException {
+ SocketChannel channel1IP = null;
+ try {
+ channel1IP = SocketChannel.open(null);
+ fail("Should throw an IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // correct
+ }
+ assertNull(channel1IP);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+ */
+ public void testReadByteBufferArray() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ ServerSocket testServer = new ServerSocket(Support_PortManager
+ .getNextPort());
+ try {
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ long readNum = CAPACITY_NORMAL;
+ readNum = testMSChannel.read(byteBuf);
+ assertEquals(0, readNum);
+ readNum = CAPACITY_NORMAL;
+ readNum = testMSChannelnull.read(byteBuf);
+ assertEquals(0, readNum);
+ } finally {
+ testServer.close();
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.read(ByteBuffer[])'
+ */
+ public void testReadByteBufferArray_BufNull() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannel.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannelnull.read(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+ */
+ public void testWriteByteBufferArray() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ byteBuf = new java.nio.ByteBuffer[CAPACITY_NORMAL];
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ testMSChannel.write(byteBuf);
+ testMSChannelnull.write(byteBuf);
+ }
+
+ /*
+ * Test method for 'java.nio.channels.SocketChannel.write(ByteBuffer[])'
+ */
+ public void testWriteByteBufferArray_BufNull() throws IOException {
+ java.nio.ByteBuffer[] byteBuf = null;
+ MockSocketChannel testMSChannelnull = new MockSocketChannel(null);
+ MockSocketChannel testMSChannel = new MockSocketChannel(
+ SelectorProvider.provider());
+ try {
+ this.channel1.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannel.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ testMSChannelnull.write(byteBuf);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testSocket_BasicStatusBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ Socket s1 = this.channel1.socket();
+ assertSocketBeforeConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_Block_BasicStatusAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ assertTrue(this.channel1.connect(localAddr1));
+
+ assertTrue(this.channel1.isConnected());
+ Socket s1 = this.channel1.socket();
+
+ assertSocketAfterConnect(s1, localAddr1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ public void testSocket_NonBlock_BasicStatusAfterConnect() throws Exception {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ boolean connected = channel1.connect(localAddr1);
+ Socket s1 = null;
+ Socket s2 = null;
+ if (!connected) {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ s1 = this.channel1.socket();
+ // status of not connected
+ assertSocketBeforeConnect(s1);
+ s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+
+ if (tryFinish()) {
+ assertTrue(this.channel1.isConnected());
+ s1 = this.channel1.socket();
+ assertSocketAfterConnect(s1, localAddr1);
+ s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+ }
+
+ public void testSocket_Block_ActionsBeforeConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ Socket s = this.channel1.socket();
+ assertSocketAction_Block_BeforeConnect(s);
+ }
+
+ public void testSocket_Block_ActionsAfterConnect() throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ assertTrue(this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.isConnected());
+ Socket s = this.channel1.socket();
+ assertSocketAction_Block_AfterConnect(s);
+
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnectBeforeFinish()
+ throws IOException {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ Socket s1 = this.channel1.socket();
+ // Action of not connected
+ assertSocketAction_NonBlock_BeforeConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+ }
+
+ public void testSocket_NonBlock_ActionsAfterConnectAfterFinish()
+ throws Exception {
+ assertFalse(this.channel1.isConnected());// not connected
+ this.channel1.configureBlocking(false);
+ channel1.connect(localAddr1);
+ if (tryFinish()) {
+ Socket s1 = this.channel1.socket();
+ assertSocketAction_NonBlock_AfterConnect(s1);
+ Socket s2 = this.channel1.socket();
+ // same
+ assertSame(s1, s2);
+ }
+ }
+
+ public void testSocket_getInetAddress() throws Exception {
+ Socket socket = channel1.socket();
+ assertNull(socket.getInetAddress());
+
+ channel1.connect(localAddr1);
+
+ assertNotNull(socket.getInetAddress());
+ assertEquals(localAddr1.getAddress(), socket.getInetAddress());
+ }
+
+ public void testSocket_getRemoteSocketAddress() throws Exception {
+ Socket socket = channel1.socket();
+ assertNull(socket.getRemoteSocketAddress());
+
+ channel1.connect(localAddr1);
+
+ assertNotNull(socket.getRemoteSocketAddress());
+ assertEquals(localAddr1, socket.getRemoteSocketAddress());
+ }
+
+ public void testSocket_getPort() throws Exception {
+ Socket socket = channel1.socket();
+ assertEquals(0, socket.getPort());
+
+ channel1.connect(localAddr1);
+
+ assertEquals(localAddr1.getPort(), socket.getPort());
+ }
+
+ public void testSocket_getLocalAddress() throws Exception {
+ Socket socket = channel1.socket();
+ assertNotNull(socket.getLocalAddress());
+
+ channel1.connect(localAddr1);
+
+ assertNotNull(socket.getLocalAddress());
+ }
+
+ public void testSocket_getLocalSocketAddress() throws Exception {
+ Socket socket = channel1.socket();
+ assertNull(socket.getLocalSocketAddress());
+
+ channel1.connect(localAddr1);
+
+ assertNotNull(socket.getLocalSocketAddress());
+ }
+
+ public void testSocket_getLocalPort() throws Exception {
+ Socket socket = channel1.socket();
+ assertEquals(-1, socket.getLocalPort());
+
+ channel1.connect(localAddr1);
+
+ assertTrue(-1 != socket.getLocalPort());
+ assertTrue(0 != socket.getLocalPort());
+ }
+
+ public void testSocket_bind() throws Exception {
+ Socket socket = channel1.socket();
+ socket.bind(new InetSocketAddress("127.0.0.1", 0));
+ assertEquals("127.0.0.1", socket.getLocalAddress().getHostAddress());
+ assertTrue(socket.getLocalPort() != -1);
+ }
+
+ private void assertSocketBeforeConnect(Socket s) throws IOException {
+ assertFalse(s.isBound());
+ assertFalse(s.isClosed());
+ assertFalse(s.isConnected());
+ assertFalse(s.getKeepAlive());
+ try {
+ s.getInputStream();
+ fail("Should throw SocketException.");
+ } catch (SocketException e) {
+ // OK.
+ }
+ assertFalse(s.getOOBInline());
+ try {
+ s.getOutputStream();
+ fail("Should throw SocketException.");
+ } catch (SocketException e) {
+ // OK.
+ }
+ assertEquals(-1, s.getSoLinger());
+ assertFalse(s.getTcpNoDelay());
+
+ assertFalse(s.isInputShutdown());
+ assertFalse(s.isOutputShutdown());
+
+ assertNull(s.getInetAddress());
+ assertEquals(s.getLocalAddress().getHostAddress(), "0.0.0.0");
+ // RI fails here. RI returns 0 while spec says unbound socket should
+ // return -1.
+ assertEquals(-1, s.getLocalPort());
+ assertFalse(s.getReuseAddress());
+ assertNull(s.getLocalSocketAddress());
+
+ // not connected
+ assertEquals(0, s.getPort());
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ assertNull(s.getRemoteSocketAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(0, s.getSoTimeout());
+ assertEquals(0, s.getTrafficClass());
+
+ }
+
+ private void assertSocketAfterConnect(Socket s, InetSocketAddress address)
+ throws IOException {
+ assertTrue(s.isBound());
+ assertFalse(s.isClosed());
+ assertTrue(s.isConnected());
+ assertFalse(s.getKeepAlive());
+
+ assertNotNull(s.getInputStream());
+ assertNotNull(s.getOutputStream());
+
+ assertFalse(s.getOOBInline());
+ assertEquals(-1, s.getSoLinger());
+ assertFalse(s.getTcpNoDelay());
+
+ assertFalse(s.isInputShutdown());
+ assertFalse(s.isOutputShutdown());
+
+ assertSame(s.getInetAddress(), address.getAddress());
+
+ assertEquals(s.getLocalAddress(), this.localAddr1.getAddress());
+ assertEquals(s.getPort(), address.getPort());
+ assertNotNull(s.getLocalSocketAddress());
+ assertTrue(s.getReceiveBufferSize() >= 8192);
+ assertEquals(s.getRemoteSocketAddress(), (SocketAddress) address);
+ // assertFalse(s.getReuseAddress());
+ assertTrue(s.getSendBufferSize() >= 8192);
+ assertEquals(0, s.getSoTimeout());
+ assertEquals(0, s.getTrafficClass());
+ }
+
+ private void assertSocketAction_Block_BeforeConnect(Socket s)
+ throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ s.connect(localAddr2);
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+
+ assertSocketAfterConnect(s, localAddr2);
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_NonBlock_BeforeConnect(Socket s)
+ throws IOException {
+ assertFalse(this.channel1.isConnected());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ try {
+ s.connect(localAddr2);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e1) {
+ // OK.
+ }
+
+ if (this.channel1.isConnectionPending()) {
+ try {
+ s.bind(localAddr2);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e1) {
+ // OK.
+ }
+ } else {
+ try {
+ s.bind(localAddr2);
+ fail("Should throw BindException");
+ } catch (BindException e1) {
+ // OK.
+ }
+ }
+
+ assertFalse(this.channel1.isConnected());
+ assertFalse(s.isConnected());
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_Block_AfterConnect(Socket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+ try {
+ s.connect(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void assertSocketAction_NonBlock_AfterConnect(Socket s)
+ throws IOException {
+ assertEquals(s.getPort(), localAddr1.getPort());
+ assertTrue(this.channel1.isConnected());
+ assertTrue(s.isConnected());
+
+ if (this.channel1.isConnectionPending()) {
+ try {
+ s.connect(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ } else {
+ try {
+ s.connect(localAddr2);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // OK.
+ }
+ }
+
+ try {
+ s.bind(localAddr2);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ s.close();
+ assertTrue(s.isClosed());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ // -------------------------------------------------------------------
+ // Tests for connect(), finishConnect(),isConnected(),isConnectionPending()
+ // These methods are very close, so we test them together, call them "CFII".
+ // -------------------------------------------------------------------
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_NoServer_NonBlock() throws Exception {
+ connectNoServerNonBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_Server_Block() throws Exception {
+ connectServerBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->close
+ */
+ public void testCFII_Norml_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->server closed-->finish-->close
+ */
+ public void testCFII_ServerClosed_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ ensureServerClosed();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->server closed-->finish-->close
+ */
+ public void testCFII_ServerClosed_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ statusNotConnected_Pending();
+ }
+ ensureServerClosed();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->server closed-->close
+ */
+ public void testCFII_ServerClosedAfterFinish_Block() throws Exception {
+ connectServerBlock();
+
+ ensureServerClosed();
+ assertTrue(this.channel1.isOpen());
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->server closed-->close
+ */
+ public void testCFII_ServerClosedAfterFinish_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ ensureServerClosed();
+ assertTrue(this.channel1.isOpen());
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * no server-->connect-->server open-->finish-->close
+ */
+ public void testCFII_ServerStartLater_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ ensureServerOpen();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ }
+
+ /**
+ * no server-->connect-->server open-->finish-->close
+ */
+ public void testCFII_ServerStartLater_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ ensureServerOpen();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_Server_Block() throws Exception {
+ connectServerBlock();
+ tryFinish();
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->finish-->close
+ */
+ public void testCFII_FinishTwice_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+ tryFinish();
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_NoServer_NonBlock()
+ throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ if (this.channel1.isOpen()) {
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ this.channel1.close();
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_Server_Block() throws Exception {
+ connectServerBlock();
+
+ if (!this.channel1.isConnected()) {
+ System.err
+ .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+ return;
+ }
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->finish-->connect-->close
+ */
+ public void testCFII_ConnectAfterFinish_Server_NonBlock() throws Exception {
+ connectServerNonBlock();
+
+ if (!this.channel1.isConnected()) {
+ System.err
+ .println("Connection fail, testCFII_ConnectAfterFinish_Server_Block is not finished.");
+ return;
+ }
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException or a ConnectionPendingException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ statusChannelClosed();
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_Server_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw an AlreadyConnectedException here.");
+ } catch (AlreadyConnectedException e) {
+ // OK.
+ }
+ statusConnected_NotPending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * connect-->connect-->finish-->close
+ */
+ public void testCFII_ConnectTwice_Server_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ statusNotConnected_Pending();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect another addr
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+
+ // connect if server closed
+ ensureServerClosed();
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectionPendingException here.");
+ } catch (ConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_Pending();
+ }
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_NoServer_Block() throws Exception {
+ // ensure
+ ensureServerClosed();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw a ConnectException here.");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw a ClosedChannelException here.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_NoServer_NonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+
+ statusChannelClosed();
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_Server_Block() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+
+ }
+
+ /**
+ * finish-->connect-->finish-->close
+ */
+ public void testCFII_FinishFirst_Server_NonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // finish
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // OK.
+ }
+ statusNotConnected_NotPending();
+ // connect
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ statusNotConnected_Pending();
+ }
+ tryFinish();
+
+ this.channel1.close();
+ statusChannelClosed();
+ }
+
+ public void testCFII_Null() throws Exception {
+ statusNotConnected_NotPending();
+ try {
+ this.channel1.connect(null);
+ fail("Should throw an IllegalArgumentException here.");
+ } catch (IllegalArgumentException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_UnsupportedType() throws Exception {
+ class SubSocketAddress extends SocketAddress {
+ private static final long serialVersionUID = 1L;
+
+ //empty
+ public SubSocketAddress() {
+ super();
+ }
+ }
+ statusNotConnected_NotPending();
+ SocketAddress newTypeAddress = new SubSocketAddress();
+ try {
+ this.channel1.connect(newTypeAddress);
+ fail("Should throw an UnsupportedAddressTypeException here.");
+ } catch (UnsupportedAddressTypeException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_Unresolved() throws IOException {
+ statusNotConnected_NotPending();
+ InetSocketAddress unresolved = new InetSocketAddress(
+ "unresolved address", 1080);
+ try {
+ this.channel1.connect(unresolved);
+ fail("Should throw an UnresolvedAddressException here.");
+ } catch (UnresolvedAddressException e) {
+ // OK.
+ }
+ }
+
+ public void testCFII_EmptyHost() throws Exception {
+ statusNotConnected_NotPending();
+ ServerSocket server = new ServerSocket(0);
+ int port = server.getLocalPort();
+ server.close();
+ try {
+ this.channel1.connect(new InetSocketAddress("", port));
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+ }
+
+ public void testCFII_CloseFirst() throws Exception {
+ this.channel1.close();
+ statusChannelClosed();
+ ensureServerOpen();
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ try {
+ this.channel1.configureBlocking(false);
+ fail("Should throw ClosedChannelException.");
+ } catch (ClosedChannelException e) {
+ // OK.
+ }
+ statusChannelClosed();
+ }
+
+ public void testCFII_StatusAfterFinish() throws Exception {
+ // 1. close server, finish must return false, check the status
+ ensureServerClosed();
+
+ // 1.1 block mode
+ assertTrue(this.channel1.isBlocking());
+ try {
+ channel1.connect(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // OK.
+ }
+ assertFalse(this.channel1.isOpen());
+
+ assertFalse(this.channel1.isOpen());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnectionPending());
+
+ // 1.2 non block mode
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ this.channel1.close();
+ } catch (ConnectException e) {
+ System.out.println(e.getMessage());
+ }
+
+ // 2. start server, finish usually return true, check the status
+ ensureServerOpen();
+
+ // 2.1 block mode
+ this.channel1 = SocketChannel.open();
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.connect(localAddr1));
+ assertTrue(this.channel1.finishConnect());
+ statusConnected_NotPending();
+ this.channel1.close();
+
+ // 2.2 non block mode
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ assertFalse(this.channel1.connect(localAddr1));
+ tryFinish();
+ this.channel1.close();
+ }
+
+ private void ensureServerClosed() throws IOException {
+ if (null != this.server1) {
+ this.server1.close();
+ assertTrue(this.server1.isClosed());
+ }
+ if (null != this.server2) {
+ this.server2.close();
+ assertTrue(this.server2.isClosed());
+ }
+ }
+
+ private void ensureServerOpen() throws IOException {
+ ensureServerClosed();
+ this.server1 = new ServerSocket(localAddr1.getPort());
+ this.server2 = new ServerSocket(localAddr2.getPort());
+ assertTrue(this.server1.isBound());
+ assertTrue(this.server2.isBound());
+ }
+
+ private void connectNoServerNonBlock() throws Exception {
+ // ensure
+ ensureServerClosed();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ assertFalse(this.channel1.connect(localAddr1));
+ statusNotConnected_Pending();
+ try {
+ assertFalse(this.channel1.finishConnect());
+ statusNotConnected_Pending();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ private void connectServerNonBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ this.channel1.configureBlocking(false);
+ statusNotConnected_NotPending();
+ // connect
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ statusNotConnected_Pending();
+ }
+ tryFinish();
+ }
+
+ private void connectServerBlock() throws Exception {
+ // ensure
+ ensureServerOpen();
+ assertTrue(this.channel1.isBlocking());
+ statusNotConnected_NotPending();
+ // connect
+ assertTrue(this.channel1.connect(localAddr1));
+ statusConnected_NotPending();
+ tryFinish();
+ }
+
+ private void statusChannelClosed() {
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isOpen());
+ }
+
+ private void statusNotConnected_NotPending() {
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private void statusNotConnected_Pending() {
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private void statusConnected_NotPending() {
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+
+ private boolean tryFinish() throws IOException {
+ /*
+ * the result of finish will be asserted in multi-thread tests.
+ */
+ boolean connected = false;
+ assertTrue(this.channel1.isOpen());
+ try {
+ connected = this.channel1.finishConnect();
+ } catch (SocketException e) {
+ // Finish connection failed, probably due to reset by peer error.
+ }
+ if (connected) {
+ statusConnected_NotPending();
+ }
+ return connected;
+ }
+
+ // -------------------------------------------------------------------
+ // Original tests. Test method for CFII with real data.
+ // -------------------------------------------------------------------
+
+ /**
+ *
+ * 'SocketChannelImpl.connect(SocketAddress)'
+ */
+ public void testCFII_Data_ConnectWithServer() throws Exception {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+
+ this.channel1.connect(localAddr1);
+
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /*
+ * Test method for 'SocketChannelImpl.connect(SocketAddress)'
+ */
+ public void testCFII_Data_ConnectWithServer_nonBlocking() throws Exception {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+
+ assertFalse(this.channel1.isBlocking());
+ boolean connected = channel1.isConnected();
+ if (!connected) {
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /*
+ * Test method for 'SocketChannelImpl.finishConnect()'
+ */
+ public void testCFII_Data_FinishConnect_nonBlocking() throws IOException {
+ ensureServerOpen();
+
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+
+ this.channel1.configureBlocking(false);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ boolean connected = channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ }
+ this.server1.accept();
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ public void testCFII_Data_FinishConnect_AddrSetServerStartLater()
+ throws IOException, InterruptedException {
+ ensureServerClosed();
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(false);
+ try {
+ SocketChannel.open(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+ assertTrue(this.channel1.isOpen());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ try {
+ this.channel1.connect(localAddr2);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+
+ assertTrue(this.channel1.isBlocking());
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertFalse(this.channel1.isConnected());
+ // finish after finish OK
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isConnected());
+ ensureServerOpen();
+ // cannot connect?
+ try {
+ assertFalse(this.channel1.finishConnect());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ tryFinish();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ public void testCFII_Data_FinishConnect_ServerStartLater()
+ throws IOException {
+ ensureServerClosed();
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectException");
+ } catch (ConnectException e) {
+ // correct
+ }
+
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ assertFalse(this.channel1.isConnected());
+ // finish after finish OK
+ assertFalse(this.channel1.isConnectionPending());
+ this.channel1 = SocketChannel.open();
+ this.channel1.configureBlocking(false);
+ this.channel1.connect(localAddr1);
+ assertFalse(this.channel1.isConnected());
+ ensureServerOpen();
+ // cannot connect?
+ try {
+ assertFalse(this.channel1.finishConnect());
+ assertFalse(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertTrue(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw ConnectionPendingException");
+ } catch (ConnectionPendingException e) {
+ // correct
+ }
+ tryFinish();
+ } catch (ConnectException e) {
+ // FIXME: assertEquals(e.getMessage(), "Connection refused");
+ }
+ }
+
+ public void testCFII_Data_FinishConnect_Blocking() throws IOException {
+ ensureServerOpen();
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ java.nio.ByteBuffer[] writeBufArr = new java.nio.ByteBuffer[1];
+ writeBufArr[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ this.channel1.configureBlocking(true);
+ try {
+ this.channel1.finishConnect();
+ fail("Should throw NoConnectionPendingException");
+ } catch (NoConnectionPendingException e) {
+ // correct
+ }
+
+ this.channel1.connect(localAddr1);
+
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ if (tryFinish()) {
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBufArr, 0, 1));
+
+ try {
+ this.channel1.connect(localAddr1);
+ fail("Should throw AlreadyConnectedException");
+ } catch (AlreadyConnectedException e) {
+ // correct
+ }
+ }
+ assertFalse(this.channel1.isRegistered());
+ tryFinish();
+ }
+
+ /**
+ * Regression test for Harmony-1947.
+ */
+ public void test_finishConnect() throws Exception {
+ SocketAddress address = new InetSocketAddress("localhost", 0);
+
+ ServerSocketChannel theServerChannel = ServerSocketChannel.open();
+ ServerSocket serversocket = theServerChannel.socket();
+ serversocket.setReuseAddress(true);
+ // Bind the socket
+ serversocket.bind(address);
+
+ boolean doneNonBlockingConnect = false;
+ // Loop so that we make sure we're definitely testing finishConnect()
+ while (!doneNonBlockingConnect) {
+ channel1 = SocketChannel.open();
+
+ // Set the SocketChannel to non-blocking so that connect(..) does
+ // not block
+ channel1.configureBlocking(false);
+ boolean connected = channel1.connect(new InetSocketAddress("localhost",serversocket.getLocalPort()));
+ if (!connected) {
+ // Now set the SocketChannel back to blocking so that
+ // finishConnect() blocks.
+ channel1.configureBlocking(true);
+ doneNonBlockingConnect = channel1.finishConnect();
+ }
+ if (doneNonBlockingConnect) {
+ tryFinish();
+ }
+ channel1.close();
+ }
+ if (!serversocket.isClosed()) {
+ serversocket.close();
+ }
+ }
+
+ // -------------------------------------------------------------------
+ // End of original tests. Test method for CFII with real data.
+ // -------------------------------------------------------------------
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+ */
+ public void test_readLjava_nio_ByteBuffer_Blocking() throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ // use OutputStream.write to send CAPACITY_NORMAL bytes data
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+
+ ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ int totalCount = 0;
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.read to read data
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = channel1.read(readContent);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation. For
+ // blocking read, it possibly returns 0 in some cases.
+ assertTimeout(startTime, TIMEOUT);
+ }
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ readContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContent.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer)
+ */
+ public void test_readLjava_nio_ByteBuffer_Nonblocking() throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < writeContent.length; i++) {
+ writeContent[i] = (byte) i;
+ }
+
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // use OutputStream.write to write CAPACITY_NORMAL bytes data.
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+
+ channel1.configureBlocking(false);
+ ByteBuffer readContent = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ int totalCount = 0;
+ int count = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.read to read data
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = channel1.read(readContent);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation.
+ assertTimeout(startTime, TIMEOUT);
+ }
+
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ assertEquals(CAPACITY_NORMAL, readContent.position());
+ readContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContent.get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+ */
+ public void test_writeLjava_nio_ByteBuffer_Blocking() throws IOException {
+ // initialize write content
+ ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent.put((byte) i);
+ }
+ writeContent.flip();
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+ // data
+ int writtenCount = channel1.write(writeContent);
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writtenCount);
+ assertEquals(CAPACITY_NORMAL, writeContent.position());
+ // use close to guarantee all data is sent
+ channel1.close();
+
+ InputStream in = acceptedSocket.getInputStream();
+ int totalCount = 0;
+ int count = 0;
+ byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ writeContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent.get(), readContent[i]);
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer)
+ */
+ public void test_writeLjava_nio_ByteBuffer_NonBlocking() throws Exception {
+ // initialize write content
+ ByteBuffer writeContent = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContent.put((byte) i);
+ }
+ writeContent.flip();
+
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+
+ channel1.configureBlocking(false);
+ int writtenTotalCount = 0;
+ int writtenCount = 0;
+ long startTime = System.currentTimeMillis();
+ // use SocketChannel.write(ByteBuffer) to write CAPACITY_NORMAL bytes
+ while (writtenTotalCount < CAPACITY_NORMAL) {
+ writtenCount = channel1.write(writeContent);
+ writtenTotalCount += writtenCount;
+ // if the channel could not finish writing in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation.
+ assertTimeout(startTime, TIMEOUT);
+ }
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writtenTotalCount);
+ assertEquals(CAPACITY_NORMAL, writeContent.position());
+ // use close to guarantee all data is sent
+ channel1.close();
+
+ InputStream in = acceptedSocket.getInputStream();
+ byte[] readContent = new byte[CAPACITY_NORMAL + 1];
+ int totalCount = 0;
+ int count = 0;
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+ // assert read content
+ assertEquals(CAPACITY_NORMAL, totalCount);
+ writeContent.flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent.get(), readContent[i]);
+ }
+ }
+
+ /*
+ * Fails if the difference between current time and start time is greater
+ * than timeout.
+ */
+ private void assertTimeout(long startTime, long timeout) {
+ long currentTime = System.currentTimeMillis();
+ if ((currentTime - startTime) > timeout) {
+ fail("Timeout");
+ }
+ }
+
+ // -------------------------------------------------
+ // Test for read/write but no real data expressed
+ // -------------------------------------------------
+
+ public void testReadByteBuffer() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ boolean connected = this.channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ }
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBuffer_Direct() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer
+ .allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ boolean connected = this.channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ }
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBuffer_Direct2() throws IOException {
+ byte[] request = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ ByteBuffer buffer = ByteBuffer.allocateDirect(128);
+
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.socket().bind(
+ new InetSocketAddress(InetAddress.getLocalHost(), 0), 5);
+ Socket client = new Socket(InetAddress.getLocalHost(), server.socket()
+ .getLocalPort());
+ client.setTcpNoDelay(false);
+ Socket worker = server.socket().accept();
+ SocketChannel workerChannel = worker.getChannel();
+
+ OutputStream out = client.getOutputStream();
+ out.write(request);
+ out.close();
+
+ buffer.limit(5);
+ int bytesRead = workerChannel.read(buffer);
+ assertEquals(5, bytesRead);
+ assertEquals(5, buffer.position());
+
+ buffer.limit(request.length);
+ bytesRead = workerChannel.read(buffer);
+ assertEquals(6, bytesRead);
+
+ buffer.flip();
+ assertEquals(request.length, buffer.limit());
+
+ assertEquals(ByteBuffer.wrap(request), buffer);
+
+ client.close();
+ worker.close();
+ server.close();
+ }
+
+ public void testReadByteBuffer_BufNull() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer readBuf = java.nio.ByteBuffer.allocate(0);
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ if (tryFinish()) {
+ try {
+ this.channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.read(readBuf));
+ }
+ this.server1.close();
+ try {
+ channel1.read((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ readBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ boolean connected = this.channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ }
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.read(ByteBuffer[], int, int)'
+ */
+ public void testReadByteBufferArrayIntInt_Direct() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ readBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ boolean connected = this.channel1.connect(localAddr1);
+ if (!connected) {
+ assertFalse(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnectionPending());
+ assertFalse(this.channel1.isConnected());
+ }
+ if (tryFinish()) {
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ assertEquals(0, this.channel1.read(readBuf, 0, 2));
+ }
+
+ this.channel1.close();
+ try {
+ channel1.read(readBuf, 0, 1);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testReadByteBufferArrayIntInt_BufNull() throws Exception {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer[] readBuf = new java.nio.ByteBuffer[2];
+ readBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ // note: blocking-mode will make the read process endless!
+ this.channel1.configureBlocking(false);
+ try {
+ channel1.read(null, 0, 0);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ if (tryFinish()) {
+
+ try {
+ channel1.read(null, 0, 0);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ channel1.read(readBuf, 0, 2);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+
+ assertEquals(0, this.channel1.read(readBuf, 0, 1));
+ }
+ this.channel1.close();
+ try {
+ channel1.read(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_Direct() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer
+ .allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf));
+
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBuffer_BufNull() throws IOException {
+ assertTrue(this.server1.isBound());
+ java.nio.ByteBuffer writeBuf = java.nio.ByteBuffer.allocate(0);
+ this.channel1.connect(localAddr1);
+ assertEquals(this.channel1.write(writeBuf), 0);
+ try {
+ this.channel1.write((java.nio.ByteBuffer) null);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+ writeBuf[0] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ writeBuf[1] = java.nio.ByteBuffer.allocate(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+ // still writes the same size as above
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+ writeBuf[0].flip();
+ writeBuf[1].flip();
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ /*
+ * SocketChannelImpl.write(ByteBuffer[], int, int)'
+ */
+ public void testWriteByteBufferArrayIntInt_Direct() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[2];
+ writeBuf[0] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ writeBuf[1] = java.nio.ByteBuffer.allocateDirect(CAPACITY_NORMAL);
+ assertFalse(this.channel1.isRegistered());
+ assertTrue(this.channel1.isBlocking());
+ assertFalse(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ try {
+ channel1.write(writeBuf, 0, 1);
+ fail("Should throw NotYetConnectedException");
+ } catch (NotYetConnectedException e) {
+ // correct
+ }
+ this.channel1.connect(localAddr1);
+ assertTrue(this.channel1.isBlocking());
+ assertTrue(this.channel1.isConnected());
+ assertFalse(this.channel1.isConnectionPending());
+ assertTrue(this.channel1.isOpen());
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 1));
+ // still writes the same size as above
+ assertEquals(CAPACITY_NORMAL, this.channel1.write(writeBuf, 0, 2));
+ writeBuf[0].flip();
+ writeBuf[1].flip();
+ assertEquals(CAPACITY_NORMAL * 2, this.channel1.write(writeBuf, 0, 2));
+ this.channel1.close();
+ try {
+ channel1.write(writeBuf);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_BufNull() throws IOException {
+ java.nio.ByteBuffer[] writeBuf = new java.nio.ByteBuffer[0];
+
+ this.channel1.connect(localAddr1);
+ try {
+ this.channel1.write(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ assertEquals(0, this.channel1.write(writeBuf, 0, 0));
+ try {
+ this.channel1.write(writeBuf, 0, 1);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ writeBuf = new java.nio.ByteBuffer[1];
+ try {
+ this.channel1.write(writeBuf, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ try {
+ this.channel1.write(writeBuf, 0, 2);
+ fail("Should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // correct
+ }
+ this.server1.close();
+ try {
+ channel1.read(null, 0, 1);
+ fail("Should throw NPE");
+ } catch (NullPointerException e) {
+ // correct
+ }
+ }
+
+ public void testWriteByteBufferArrayIntInt_SizeError() throws IOException {
+ java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+ this.channel1.connect(localAddr1);
+ assertEquals(0, this.channel1.write(buf, 0, 0));
+ try {
+ this.channel1.write(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.write(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.write(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.write(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ this.server1.close();
+ }
+
+ public void testReadByteBufferArrayIntInt_SizeError() throws IOException {
+ java.nio.ByteBuffer[] buf = new java.nio.ByteBuffer[1];
+ this.channel1.connect(localAddr1);
+ assertEquals(0, this.channel1.read(buf, 0, 0));
+ try {
+ this.channel1.read(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.read(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.read(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.read(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ this.channel1.read(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ this.server1.close();
+ }
+
+ /*
+ * ==========================================================================
+ * Tests for read/write real data
+ * ==========================================================================
+ */
+
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[])
+ */
+ public void test_read$LByteBuffer() throws IOException {
+ MockSocketChannel sc = new MockSocketChannel(null);
+ ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+ // Verify that calling read(ByteBuffer[]) leads to the method
+ // read(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and targets.length as the third parameter.
+ sc.read(byteBufferArray);
+ assertTrue(sc.isReadCalled);
+ }
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read$LByteBufferII_blocking() throws Exception {
+ assert_read$LByteBuffer(true);
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#read(ByteBuffer[],int,int)
+ */
+ public void test_read$LByteBufferII_nonblocking() throws Exception {
+ assert_read$LByteBuffer(false);
+ }
+
+ private void assert_read$LByteBuffer(boolean isBlocking) throws IOException {
+ // initialize write content
+ byte[] writeContent = new byte[CAPACITY_NORMAL * 2];
+ for (int i = 0; i < CAPACITY_NORMAL * 2; i++) {
+ writeContent[i] = (byte) i;
+ }
+ ByteBuffer[] readContents = new ByteBuffer[2];
+ readContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ readContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL + 1);
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // use OutputStream.write to send CAPACITY_NORMAL * 2 bytes data
+ OutputStream out = acceptedSocket.getOutputStream();
+ out.write(writeContent);
+ // use close to guarantee all data is sent
+ acceptedSocket.close();
+ // configure block/nonblock mode
+ channel1.configureBlocking(isBlocking);
+ long startTime = System.currentTimeMillis();
+ long totalRead = 0;
+ long countRead = 0;
+
+ while (totalRead <= CAPACITY_NORMAL * 2) {
+ countRead = channel1.read(readContents, 0, 2);
+ if (0 == countRead && !readContents[1].hasRemaining()) {
+ // read returns 0 because readContents is full
+ break;
+ }
+ if (EOF == countRead) {
+ break;
+ }
+ totalRead += countRead;
+ // if the channel could not finish reading in TIMEOUT ms, the
+ // test fails. It is used to guarantee the test never hangs even
+ // if there are bugs of SocketChannel implementation. For
+ // blocking read, it possibly returns 0 in some cases.
+ assertTimeout(startTime, TIMEOUT);
+ }
+
+ // assert total bytes read and the position of ByteBuffers
+ assertEquals(CAPACITY_NORMAL * 2, totalRead);
+ assertEquals(CAPACITY_NORMAL, readContents[0].position());
+ assertEquals(CAPACITY_NORMAL, readContents[1].position());
+ // assert read content
+ readContents[0].flip();
+ readContents[1].flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContent[i], readContents[0].get());
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ assertEquals(writeContent[i], readContents[1].get());
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_blocking() throws Exception {
+ assert_write$LByteBuffer(true);
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[],int,int)
+ */
+ public void test_write$LByteBufferII_nonblocking()
+ throws Exception {
+ assert_write$LByteBuffer(false);
+ }
+
+ private void assert_write$LByteBuffer(boolean isBlocking)
+ throws IOException {
+ // initialize write contents
+ ByteBuffer writeContents[] = new ByteBuffer[2];
+ writeContents[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ writeContents[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ writeContents[0].put((byte) i);
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ writeContents[1].put((byte) i);
+ }
+ writeContents[0].flip();
+ writeContents[1].flip();
+ // establish connection
+ channel1.connect(localAddr1);
+ Socket acceptedSocket = server1.accept();
+ // set blocking/nonblocking mode
+ channel1.configureBlocking(isBlocking);
+
+ assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 0, 1));
+ assertEquals(CAPACITY_NORMAL, channel1.write(writeContents, 1, 1));
+
+ // assert written count and ByteBuffer position
+ assertEquals(CAPACITY_NORMAL, writeContents[0].position());
+ assertEquals(CAPACITY_NORMAL, writeContents[1].position());
+ // use close to guarantee all data is sent
+ channel1.close();
+ InputStream in = acceptedSocket.getInputStream();
+ byte[] readContent = new byte[CAPACITY_NORMAL * 2 + 1];
+ int totalCount = 0;
+ int count = 0;
+ // if the channel could not finish reading in TIMEOUT ms, the test
+ // fails. It is used to guarantee the test never hangs even if there
+ // are bugs of SocketChannel implementation.
+ acceptedSocket.setSoTimeout(TIMEOUT);
+ // use InputStream.read to read data.
+ while (totalCount <= CAPACITY_NORMAL) {
+ count = in.read(readContent, totalCount, readContent.length
+ - totalCount);
+ if (EOF == count) {
+ break;
+ }
+ totalCount += count;
+ }
+ // assert read content
+ assertEquals(CAPACITY_NORMAL * 2, totalCount);
+ writeContents[0].flip();
+ writeContents[1].flip();
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ assertEquals(writeContents[0].get(), readContent[i]);
+ }
+ for (int i = CAPACITY_NORMAL; i < CAPACITY_NORMAL * 2; i++) {
+ assertEquals(writeContents[1].get(), readContent[i]);
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer() throws IOException {
+ MockSocketChannel sc = new MockSocketChannel(null);
+ ByteBuffer [] byteBufferArray = { ByteBuffer.allocate(1), ByteBuffer.allocate(1)};
+ // Verify that calling write(ByteBuffer[]) leads to the method
+ // write(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and sources.length as the third parameter.
+ sc.write(byteBufferArray);
+ assertTrue(sc.isWriteCalled);
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_writev() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ SocketChannel sock = ssc.accept();
+ ByteBuffer[] buf = { ByteBuffer.allocate(10), ByteBuffer.allocateDirect(20) };
+
+ while (buf[0].remaining() != 0 && buf[1].remaining() !=0) {
+ assertTrue(sc.write(buf, 0, 2) >= 0);
+ }
+
+ ByteBuffer target = ByteBuffer.allocate(30);
+
+ while (target.remaining() != 0) {
+ assertTrue(sock.read(target) >=0);
+ }
+
+ ssc.close();
+ sc.close();
+ sock.close();
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_writev2() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ ssc.socket().bind(null);
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ boolean connected = sc.connect(ssc.socket().getLocalSocketAddress());
+ SocketChannel sock = ssc.accept();
+ if (!connected) {
+ sc.finishConnect();
+ }
+
+ ByteBuffer buf1 = ByteBuffer.allocate(10);
+ sc.socket().setSendBufferSize(512);
+ int bufSize = sc.socket().getSendBufferSize();
+ ByteBuffer buf2 = ByteBuffer.allocate(bufSize * 10);
+
+ ByteBuffer[] sent = new ByteBuffer[2];
+ sent[0] = buf1;
+ sent[1] = buf2;
+
+ long whole = buf1.remaining() + buf2.remaining();
+
+ long write = sc.write(sent);
+ ssc.close();
+ sc.close();
+ sock.close();
+
+ assertTrue(whole == (write + buf1.remaining() + buf2.remaining()));
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ *
+ * In non-blocking mode, the native system call will return EAGAIN/EWOULDBLOCK error
+ * code on Linux/Unix and return WSATRY_AGAIN/WSAEWOULDBLOCK error code on Windows.
+ * These error code means try again but not fatal error, so we should not throw exception.
+ */
+ public void test_write$NonBlockingException() throws Exception {
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ ssc.socket().bind(null);
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ boolean connected = sc.connect(ssc.socket().getLocalSocketAddress());
+ SocketChannel sock = ssc.accept();
+ if (!connected) {
+ sc.finishConnect();
+ }
+
+ try {
+ for (int i = 0; i < 100; i++) {
+ ByteBuffer buf1 = ByteBuffer.allocate(10);
+ sc.socket().setSendBufferSize(512);
+ int bufSize = sc.socket().getSendBufferSize();
+ ByteBuffer buf2 = ByteBuffer.allocate(bufSize * 10);
+
+ ByteBuffer[] sent = new ByteBuffer[2];
+ sent[0] = buf1;
+ sent[1] = buf2;
+
+ sc.write(sent);
+ }
+ } finally {
+ ssc.close();
+ sc.close();
+ sock.close();
+ }
+
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer2() throws IOException {
+ // Set-up
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.socket().bind(null);
+ SocketChannel client = SocketChannel.open();
+ client.connect(server.socket().getLocalSocketAddress());
+ SocketChannel worker = server.accept();
+
+ // Test overlapping buffers
+ byte[] data = "Hello world!".getBytes("UTF-8");
+ ByteBuffer[] buffers = new ByteBuffer[3];
+ buffers[0] = ByteBuffer.wrap(data, 0, 6);
+ buffers[1] = ByteBuffer.wrap(data, 6, data.length - 6);
+ buffers[2] = ByteBuffer.wrap(data);
+
+ // Write them out, read what we wrote and check it
+ client.write(buffers);
+ client.close();
+ ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+ while (EOF != worker.read(readBuffer)) {};
+ readBuffer.flip();
+ Buffer expected = ByteBuffer.allocate(1024).put(data).put(data).flip();
+ assertEquals(expected, readBuffer);
+
+ // Tidy-up
+ worker.close();
+ server.close();
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer_buffers() throws IOException {
+ // Set-up
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.socket().bind(null);
+ SocketChannel client = SocketChannel.open();
+ client.connect(server.socket().getLocalSocketAddress());
+ SocketChannel worker = server.accept();
+
+ // A variety of buffer types to write
+ byte[] data = "Hello world!".getBytes("UTF-8");
+ ByteBuffer[] buffers = new ByteBuffer[3];
+ buffers[0] = ByteBuffer.wrap(data, 0, 2);
+ assertFalse(buffers[0].isDirect());
+ assertTrue(buffers[0].hasArray());
+
+ buffers[1] = ByteBuffer.wrap(data, 2, 4).asReadOnlyBuffer();
+ assertFalse(buffers[1].isDirect());
+ assertFalse(buffers[1].hasArray());
+
+ buffers[2] = ByteBuffer.allocateDirect(42);
+ buffers[2].put(data, 6, data.length - 6);
+ buffers[2].flip();
+ assertTrue(buffers[2].isDirect());
+ // Android's direct buffers do have a backing array.
+ assertTrue(buffers[2].hasArray());
+
+ // Write them out, read what we wrote and check it
+ client.write(buffers);
+ client.close();
+ ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+ while (EOF != worker.read(readBuffer)) {};
+ readBuffer.flip();
+ assertEquals(ByteBuffer.wrap(data), readBuffer);
+
+ // Tidy-up
+ worker.close();
+ server.close();
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer_writes() throws IOException {
+ // Set-up
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.socket().bind(null);
+ SocketChannel client = SocketChannel.open();
+ client.connect(server.socket().getLocalSocketAddress());
+ SocketChannel worker = server.accept();
+
+ // Data to write
+ byte[] data = "Hello world!".getBytes("UTF-8");
+ ByteBuffer[] buffers = new ByteBuffer[3];
+ buffers[0] = ByteBuffer.wrap(data, 0, 6);
+ buffers[1] = ByteBuffer.wrap("world!".getBytes("UTF-8"));
+ buffers[2] = buffers[0];
+ assertTrue(buffers[0].hasArray());
+
+ // Test a sequence of write calls
+ client.write(buffers, 0, 0); // write nothing
+ client.write(buffers, 1, 0); // write nothing
+ client.write(buffers, 0, 1); // write "Hello "
+ assertEquals("Failed to drain buffer 0", 0, buffers[0].remaining());
+ assertEquals("Shouldn't touch buffer 1", buffers[1].limit(), buffers[1]
+ .remaining());
+ client.write(buffers, 0, 2); // writes "world!"
+ assertEquals("Failed to drain buffer 1", 0, buffers[1].remaining());
+ client.write(buffers, 0, 3); // write nothing
+ client.close();
+
+ // Read what we wrote and check it
+ ByteBuffer readBuffer = ByteBuffer.allocate(1024);
+ while (EOF != worker.read(readBuffer)) {};
+ readBuffer.flip();
+ assertEquals(ByteBuffer.wrap(data), readBuffer);
+
+ // Tidy-up
+ worker.close();
+ server.close();
+ }
+
+ /**
+ * @tests java.nio.channels.SocketChannel#write(ByteBuffer[])
+ */
+ public void test_write$LByteBuffer_invalid() throws IOException {
+ // Set-up
+ ServerSocketChannel server = ServerSocketChannel.open();
+ server.socket().bind(null);
+
+ SocketChannel client = SocketChannel.open();
+ client.connect(server.socket().getLocalSocketAddress());
+
+ SocketChannel worker = server.accept();
+
+ // Do some stuff
+ try {
+ client.write((ByteBuffer[]) null);
+ fail("Should throw a NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ client.write((ByteBuffer[]) null, 0, 0);
+ fail("Should throw a NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ client.write((ByteBuffer[]) null, 1, 0);
+ fail("Should throw a NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ client.write((ByteBuffer[]) null, 0, 1);
+ fail("Should throw a NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ client.write((ByteBuffer[]) null, 1, 1);
+ fail("Should throw a NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] buffers = new ByteBuffer[1];
+ buffers[0] = ByteBuffer.wrap("Hello ".getBytes("UTF-8"));
+
+ try {
+ client.write(buffers, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ client.write(buffers, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ client.write(buffers, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ client.write(buffers, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ client.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ // Tidy-up
+ worker.close();
+ client.close();
+ server.close();
+ }
+
+ public void testSocket_configureblocking() throws IOException {
+ byte[] serverWBuf = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < serverWBuf.length; i++) {
+ serverWBuf[i] = (byte) i;
+ }
+ java.nio.ByteBuffer buf = java.nio.ByteBuffer
+ .allocate(CAPACITY_NORMAL + 1);
+ channel1.connect(localAddr1);
+ server1.accept();
+ Socket sock = this.channel1.socket();
+ channel1.configureBlocking(false);
+ assertFalse(channel1.isBlocking());
+ OutputStream channelSocketOut = sock.getOutputStream();
+ try {
+ // write operation is not allowed in non-blocking mode
+ channelSocketOut.write(buf.array());
+ fail("Non-Blocking mode should cause IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // correct
+ }
+ channel1.configureBlocking(true);
+ assertTrue(channel1.isBlocking());
+ // write operation is allowed in blocking mode
+ channelSocketOut.write(buf.array());
+ }
+
+ /**
+ * @tests SocketChannel#read(ByteBuffer[], int, int) when remote server
+ * closed
+ */
+ public void test_socketChannel_read_ByteBufferII_remoteClosed()
+ throws Exception {
+ // regression 1 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ ssc.accept().close();
+ ByteBuffer[] buf = { ByteBuffer.allocate(10) };
+ assertEquals(-1, sc.read(buf, 0, 1));
+ ssc.close();
+ sc.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer[], int, int)
+ */
+ public void test_socketChannel_write_ByteBufferII() throws Exception {
+ // regression 2 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ SocketChannel sock = ssc.accept();
+ ByteBuffer[] buf = { ByteBuffer.allocate(10), null };
+ try {
+ sc.write(buf, 0, 2);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ ssc.close();
+ sc.close();
+ ByteBuffer target = ByteBuffer.allocate(10);
+ assertEquals(-1, sock.read(target));
+ }
+
+ /**
+ * @tests SocketChannel#read(ByteBuffer[], int, int) with a null ByteBuffer
+ */
+ public void test_socketChannel_read_ByteBufferII_bufNULL() throws Exception {
+ // regression 3 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ ssc.accept();
+ ByteBuffer[] buf = new ByteBuffer[2];
+ buf[0] = ByteBuffer.allocate(1);
+ // let buf[1] be null
+ try {
+ sc.read(buf, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ ssc.close();
+ sc.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer) after close
+ */
+ public void test_socketChannel_write_close() throws Exception {
+ // regression 4 for HARMONY-549
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ SocketChannel sock = ssc.accept();
+ ByteBuffer buf = null;
+ ssc.close();
+ sc.close();
+ try {
+ sc.write(buf);
+ fail("should throw NPE");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ sock.close();
+ }
+
+ /**
+ * @tests SocketChannel#write(ByteBuffer) if position is not zero
+ */
+ public void test_socketChannel_write_ByteBuffer_posNotZero()
+ throws Exception {
+ // regression 5 for HARMONY-549
+ final String testStr = "Hello World";
+ ByteBuffer readBuf = ByteBuffer.allocate(11);
+ ByteBuffer buf = ByteBuffer.wrap(testStr.getBytes());
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.socket().bind(localAddr2);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(localAddr2);
+ buf.position(2);
+ ssc.accept().write(buf);
+ assertEquals(9, sc.read(readBuf));
+ buf.flip();
+ readBuf.flip();
+ byte[] read = new byte[9];
+ byte[] write = new byte[11];
+ buf.get(write);
+ readBuf.get(read);
+ for (int i = 0; i < 9; i++) {
+ assertEquals(read[i], write[i + 2]);
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#read(ByteBuffer[])
+ */
+ public void test_read_$ByteBuffer_Blocking() throws IOException {
+ // regression test for Harmony-728
+ byte[] data = new byte[CAPACITY_NORMAL];
+ for (int i = 0; i < CAPACITY_NORMAL; i++) {
+ data[i] = (byte) i;
+ }
+ ByteBuffer[] buf = new ByteBuffer[2];
+ buf[0] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ buf[1] = ByteBuffer.allocate(CAPACITY_NORMAL);
+ channel1.connect(localAddr1);
+ Socket socket = null;
+ try {
+ socket = server1.accept();
+ OutputStream out = socket.getOutputStream();
+ out.write(data);
+ // should not block here
+ channel1.read(buf);
+ } finally {
+ if (null != socket) {
+ socket.close();
+ }
+ }
+ }
+
+ public void test_socket_getOutputStream_nonBlocking_read_Exception() throws IOException {
+ byte[] buf = new byte[1];
+ channel1.connect(this.localAddr1);
+ InputStream is = channel1.socket().getInputStream();
+ channel1.configureBlocking(false);
+ try {
+ is.read();
+ fail();
+ } catch (IllegalBlockingModeException expected) {
+ }
+ try {
+ is.read(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ is.read(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ is.close();
+
+ try {
+ is.read();
+ fail();
+ } catch (IllegalBlockingModeException expected) {
+ }
+ try {
+ is.read(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ is.read(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_socket_getOutputStream_blocking_read_Exception() throws IOException {
+ byte[] buf = new byte[1];
+ channel1.connect(this.localAddr1);
+ InputStream is = channel1.socket().getInputStream();
+ try {
+ is.read(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ is.read(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ is.close();
+
+ try {
+ is.read(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ is.read(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ is.read(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_socket_getOutputStream_nonBlocking_write_Exception() throws IOException {
+ byte[] buf = new byte[1];
+ channel1.connect(this.localAddr1);
+ OutputStream os = channel1.socket().getOutputStream();
+ channel1.configureBlocking(false);
+
+ try {
+ os.write(1);
+ fail();
+ } catch (IllegalBlockingModeException expected) {
+ }
+ try {
+ os.write(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ os.write(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ os.close();
+
+ try {
+ os.write(1);
+ fail();
+ } catch (IllegalBlockingModeException expected) {
+ }
+ try {
+ os.write(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ os.write(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ public void test_socket_getOutputStream_blocking_write_Exception() throws IOException {
+ byte[] buf = new byte[1];
+ channel1.connect(this.localAddr1);
+ OutputStream os = channel1.socket().getOutputStream();
+ try {
+ os.write(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ os.write(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ os.close();
+
+ try {
+ os.write(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ os.write(buf, -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 0, 2);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(buf, 2, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+ try {
+ os.write(null, 0, 0);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ }
+
+ /**
+ * @tests SocketChannelImpl#socket().getOutputStream().write(int)
+ */
+ public void test_socket_getOutputStream_write_oneByte()
+ throws IOException {
+
+ // Regression test for Harmony-3475
+
+ int MAGIC = 123;
+
+ channel1.connect(this.localAddr1);
+
+ OutputStream os = channel1.socket().getOutputStream();
+
+ Socket acceptedSocket = server1.accept();
+
+ InputStream in = acceptedSocket.getInputStream();
+
+ os.write(MAGIC);
+ channel1.close();
+
+ int lastByte = in.read();
+ if (lastByte == -1) {
+ fail("Server received nothing. Expected 1 byte.");
+ } else if (lastByte != MAGIC) {
+ fail("Server received wrong single byte: " + lastByte +
+ ", expected: " + MAGIC);
+ }
+
+ lastByte = in.read();
+ if (lastByte != -1) {
+ fail("Server received too long sequence. Expected 1 byte.");
+ }
+ }
+
+ public void testSocket_setOptions() throws IOException {
+ channel1.connect(localAddr1);
+ Socket socket = channel1.socket();
+
+ ByteBuffer buffer = ByteBuffer.wrap(new byte[] {1, 2, 3});
+ socket.setKeepAlive(true);
+ channel1.write(buffer);
+
+ socket.setOOBInline(true);
+ channel1.write(buffer);
+
+ socket.setReceiveBufferSize(100);
+ channel1.write(buffer);
+
+ socket.setReuseAddress(true);
+ channel1.write(buffer);
+
+ socket.setSendBufferSize(100);
+ channel1.write(buffer);
+
+ socket.setSoLinger(true, 100);
+ channel1.write(buffer);
+
+ socket.setSoTimeout(1000);
+ channel1.write(buffer);
+
+ socket.setTcpNoDelay(true);
+ channel1.write(buffer);
+
+ socket.setTrafficClass(10);
+ channel1.write(buffer);
+ }
+
+ class MockSocketChannel extends SocketChannel{
+
+ private boolean isWriteCalled = false;
+
+ private boolean isReadCalled = false;
+
+ public MockSocketChannel(SelectorProvider provider){
+ super(provider);
+ }
+
+ public Socket socket() {
+ return null;
+ }
+
+ public boolean isConnected() {
+ return false;
+ }
+
+ public boolean isConnectionPending() {
+ return false;
+ }
+
+ public boolean connect(SocketAddress address) throws IOException {
+ return false;
+ }
+
+ public boolean finishConnect() throws IOException {
+ return false;
+ }
+
+ public int read(ByteBuffer target) throws IOException {
+ return 0;
+ }
+
+ public long read(ByteBuffer[] targets, int offset, int length) throws IOException {
+ // Verify that calling read(ByteBuffer[]) leads to the method
+ // read(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and targets.length as the third parameter.
+ if(0 == offset && length == targets.length){
+ isReadCalled = true;
+ }
+ return 0;
+ }
+
+ public int write(ByteBuffer source) throws IOException {
+ return 0;
+ }
+
+ public long write(ByteBuffer[] sources, int offset, int length) throws IOException {
+ // Verify that calling write(ByteBuffer[]) leads to the method
+ // write(ByteBuffer[], int, int) being called with a 0 for the
+ // second parameter and sources.length as the third parameter.
+ if(0 == offset && length == sources.length){
+ isWriteCalled = true;
+ }
+ return 0;
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ // empty
+ }
+
+ protected void implConfigureBlocking(boolean blockingMode) throws IOException {
+ // empty
+ }
+
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
new file mode 100644
index 0000000..53fdae4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/SourceChannelTest.java
@@ -0,0 +1,554 @@
+/* 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.tests.java.nio.channels;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Pipe;
+import java.nio.channels.SelectionKey;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for java.nio.channels.Pipe.SourceChannel
+ */
+public class SourceChannelTest extends TestCase {
+
+ private static final int BUFFER_SIZE = 5;
+
+ private static final String ISO8859_1 = "ISO8859-1";
+
+ private Pipe pipe;
+
+ private Pipe.SinkChannel sink;
+
+ private Pipe.SourceChannel source;
+
+ private ByteBuffer buffer;
+
+ private ByteBuffer positionedBuffer;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ buffer = ByteBuffer.wrap("bytes".getBytes(ISO8859_1));
+ positionedBuffer = ByteBuffer.wrap("12345bytes".getBytes(ISO8859_1));
+ positionedBuffer.position(BUFFER_SIZE);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#validOps()
+ */
+ public void test_validOps() {
+ assertEquals(SelectionKey.OP_READ, source.validOps());
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_DataAvailable() throws IOException {
+ // if anything can read, read method will not block
+ sink.write(ByteBuffer.allocate(1));
+ int count = source.read(ByteBuffer.allocate(10));
+ assertEquals(1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_Exception() throws IOException {
+ ByteBuffer nullBuf = null;
+ try {
+ source.read(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBuf);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBuf);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ count = source.read(readBuf);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ source.close();
+ try {
+ source.read(readBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBuf);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer nullBuf = null;
+ try {
+ source.read(nullBuf);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] bufArray = null;
+ try {
+ source.read(bufArray);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray = {nullBuf};
+ try {
+ source.read(nullBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[])
+ */
+ public void test_read_$LByteBuffer() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ // open new pipe everytime, will be closed in finally block
+ pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ try {
+ long writeCount = sink.write(bufArray);
+ assertEquals(10, writeCount);
+ // invoke close to ensure all data will be sent out
+ sink.close();
+ // read until EOF is meet or readBufArray is full.
+ ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+ ByteBuffer.allocate(BUFFER_SIZE) };
+ long totalCount = 0;
+ do {
+ long count = source.read(readBufArray);
+ if (count < 0) {
+ break;
+ }
+ if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+ // source.read returns 0 because readBufArray is full
+ break;
+ }
+ totalCount += count;
+ } while (totalCount <= 10);
+ // assert read result
+ for (ByteBuffer readBuf : readBufArray) {
+ // RI may fail because of its bug implementation
+ assertEquals(BUFFER_SIZE, readBuf.position());
+ assertEquals("bytes",
+ new String(readBuf.array(), ISO8859_1));
+ }
+ } finally {
+ // close pipe everytime
+ sink.close();
+ source.close();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_Exception() throws IOException {
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+ try {
+ source.read(nullBufArray2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBufArray);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBufArray);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ assertTrue(readBuf.hasRemaining());
+ count = source.read(readBufArray);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBuffer_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ source.close();
+ try {
+ source.read(readBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBufArray);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer[], int, int)
+ */
+ public void test_read_$LByteBufferII() throws IOException {
+ ByteBuffer[] bufArray = { buffer, positionedBuffer };
+ boolean[] sinkBlockingMode = { true, true, false, false };
+ boolean[] sourceBlockingMode = { true, false, true, false };
+ for (int i = 0; i < sinkBlockingMode.length; ++i) {
+ Pipe pipe = Pipe.open();
+ sink = pipe.sink();
+ source = pipe.source();
+
+ sink.configureBlocking(sinkBlockingMode[i]);
+ source.configureBlocking(sourceBlockingMode[i]);
+
+ buffer.position(0);
+ positionedBuffer.position(BUFFER_SIZE);
+ try {
+ sink.write(bufArray);
+ // invoke close to ensure all data will be sent out
+ sink.close();
+ // read until EOF is meet or readBufArray is full.
+ ByteBuffer[] readBufArray = { ByteBuffer.allocate(BUFFER_SIZE),
+ ByteBuffer.allocate(BUFFER_SIZE) };
+ long totalCount = 0;
+ do {
+ long count = source.read(readBufArray, 0, 2);
+ if (count < 0) {
+ break;
+ }
+ if (0 == count && BUFFER_SIZE == readBufArray[1].position()) {
+ // source.read returns 0 because readBufArray is full
+ break;
+ }
+ totalCount += count;
+ } while (totalCount != 10);
+
+ // assert read result
+ for (ByteBuffer readBuf : readBufArray) {
+ // RI may fail because of its bug implementation
+ assertEquals(BUFFER_SIZE, readBuf.position());
+ assertEquals("bytes",
+ new String(readBuf.array(), ISO8859_1));
+ }
+ } finally {
+ sink.close();
+ source.close();
+ }
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_Exception() throws IOException {
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef, 0, 1);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ source.read(nullBufArrayRef, 0, -1);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ source.read(new ByteBuffer[0], 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ source.read(new ByteBuffer[0], -1, 0);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1, 0, 1);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+ try {
+ source.read(nullBufArray1, 1, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 2);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_SinkClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ sink.write(buffer);
+ sink.close();
+ long count = source.read(readBufArray, 0, 1);
+ assertEquals(BUFFER_SIZE, count);
+ // readBuf is full, read 0 byte expected
+ count = source.read(readBufArray);
+ assertEquals(0, count);
+ // readBuf is not null, -1 is expected
+ readBuf.position(0);
+ count = source.read(readBufArray, 0, 1);
+ assertEquals(-1, count);
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#read(ByteBuffer)
+ */
+ public void test_read_$LByteBufferII_SourceClosed() throws IOException {
+ ByteBuffer readBuf = ByteBuffer.allocate(BUFFER_SIZE);
+ ByteBuffer[] readBufArray = { readBuf };
+ source.close();
+ try {
+ source.read(readBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ readBuf.position(BUFFER_SIZE);
+ try {
+ // readBuf is full
+ source.read(readBufArray, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArrayRef = null;
+ try {
+ source.read(nullBufArrayRef, 0, 1);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ try {
+ source.read(nullBufArrayRef, 0, -1);
+ fail();
+ } catch (NullPointerException expected) {
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ source.read(new ByteBuffer[0], 0, -1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ try {
+ source.read(new ByteBuffer[0], -1, 1);
+ fail();
+ } catch (IndexOutOfBoundsException expected) {
+ }
+
+ // ByteBuffer array contains null element
+ ByteBuffer nullBuf = null;
+ ByteBuffer[] nullBufArray1 = { nullBuf };
+ try {
+ source.read(nullBufArray1, 0, 1);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, 0, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 0);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+ try {
+ source.read(nullBufArray1, -1, 1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ ByteBuffer[] nullBufArray2 = { buffer, nullBuf };
+
+ try {
+ source.read(nullBufArray1, 1, -1);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 3);
+ fail("should throw IndexOutOfBoundsException");
+ } catch (IndexOutOfBoundsException e) {
+ // expected
+ }
+
+ try {
+ source.read(nullBufArray2, 0, 2);
+ fail("should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.channels.Pipe.SourceChannel#close()
+ */
+ public void test_close() throws IOException {
+ sink.close();
+ assertFalse(sink.isOpen());
+ }
+
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java
new file mode 100644
index 0000000..8995394
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnixSelectorTest.java
@@ -0,0 +1,116 @@
+/* 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.tests.java.nio.channels;
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import junit.framework.TestCase;
+
+public class UnixSelectorTest extends TestCase {
+ static class Server {
+ ServerSocketChannel serverChannel = ServerSocketChannel.open();
+ ServerSocket socket = null;
+
+ Server() throws Exception {
+ serverChannel.configureBlocking(false);
+ }
+
+ public void initialize() throws Exception {
+ this.socket = serverChannel.socket();
+ socket.bind(null);
+ }
+
+ public void accept() {
+ Thread serverThread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ while (serverChannel.accept() == null) {
+ Thread.sleep(1000);
+ }
+ } catch (Exception e) {}
+ }
+ });
+ serverThread.start();
+ }
+
+ public void close() throws Exception{
+ serverChannel.close();
+ }
+ }
+
+ public void testSelectorAcceptAndRead() throws Exception {
+ Selector sel0 = Selector.open();
+ Selector sel1 = Selector.open();
+ Server server = new Server();
+ SelectionKey mkey0 = server.serverChannel.register(sel0, SelectionKey.OP_ACCEPT);
+ server.serverChannel.register(sel1, SelectionKey.OP_ACCEPT);
+
+ // HUP is treating as acceptable
+ assertEquals(1, sel0.select(100));
+ assertEquals(true, sel0.selectedKeys().contains(mkey0));
+ server.initialize();
+ // after bind can not accept
+ assertEquals(0, sel1.select(100));
+ server.accept();
+ Thread.sleep(1000);
+ SocketChannel socketChannel = SocketChannel.open();
+ socketChannel.configureBlocking(false);
+ Selector sel2 = Selector.open();
+ socketChannel.register(sel2, SelectionKey.OP_WRITE);
+ boolean isConnected = socketChannel.connect(server.socket.getLocalSocketAddress());
+ if (!isConnected) {
+ socketChannel.finishConnect();
+ }
+
+ assertEquals(true, socketChannel.isConnected());
+ server.close();
+ Thread.sleep(3000);
+ assertEquals(true, socketChannel.isConnected());
+ assertEquals(1, sel2.select(100));
+ }
+
+ public void testSelectUnConnectedChannel() throws Exception {
+ SocketChannel socketChannel2 = SocketChannel.open();
+ socketChannel2.configureBlocking(false);
+ Selector sel3 = Selector.open();
+ SelectionKey mkey3 = socketChannel2.register(sel3, SelectionKey.OP_WRITE);
+ // HUP is also treating as writable
+ assertEquals(1, sel3.select(100));
+ assertEquals(false, mkey3.isConnectable());
+ // even the channel is not connected, the selector could be writable
+ assertEquals(false, socketChannel2.isConnected());
+ assertEquals(true, mkey3.isWritable());
+
+ Selector sel4 = Selector.open();
+ SelectionKey mkey4 = socketChannel2.register(sel4, SelectionKey.OP_CONNECT);
+ assertEquals(1, sel4.select(100));
+ assertEquals(false, mkey4.isWritable());
+ assertEquals(true, mkey4.isConnectable());
+
+ Selector sel5 = Selector.open();
+ SelectionKey mkey5 = socketChannel2.register(sel5, SelectionKey.OP_CONNECT | SelectionKey.OP_WRITE);
+ assertEquals(1, sel5.select(100));
+ assertEquals(true, mkey5.isWritable());
+ assertEquals(true, mkey5.isConnectable());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
new file mode 100644
index 0000000..827dcd7
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnresolvedAddressExceptionTest.java
@@ -0,0 +1,54 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.UnresolvedAddressException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnresolvedAddressException
+ */
+public class UnresolvedAddressExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.UnresolvedAddressException#UnresolvedAddressException()}
+ */
+ public void test_Constructor() {
+ UnresolvedAddressException e = new UnresolvedAddressException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnresolvedAddressException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnresolvedAddressException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
new file mode 100644
index 0000000..e032ea4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/UnsupportedAddressTypeExceptionTest.java
@@ -0,0 +1,55 @@
+/* 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.tests.java.nio.channels;
+
+import java.nio.channels.UnsupportedAddressTypeException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Tests for UnsupportedAddressTypeException
+ */
+public class UnsupportedAddressTypeExceptionTest extends TestCase {
+
+ /**
+ * @tests {@link java.nio.channels.UnsupportedAddressTypeException#UnsupportedAddressTypeException()}
+ */
+ public void test_Constructor() {
+ UnsupportedAddressTypeException e = new UnsupportedAddressTypeException();
+ assertNull(e.getMessage());
+ assertNull(e.getLocalizedMessage());
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnsupportedAddressTypeException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this,
+ new UnsupportedAddressTypeException());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
new file mode 100644
index 0000000..5072dc9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractInterruptibleChannelTest.java
@@ -0,0 +1,135 @@
+/* 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.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.AsynchronousCloseException;
+import java.nio.channels.spi.AbstractInterruptibleChannel;
+
+import junit.framework.TestCase;
+
+public class AbstractInterruptibleChannelTest extends TestCase {
+
+ /**
+ * @tests AbstractInterruptibleChannel#close()
+ */
+ public void test_close() throws IOException {
+ MockInterruptibleChannel testMiChannel = new MockInterruptibleChannel();
+ assertTrue(testMiChannel.isOpen());
+ testMiChannel.isImplCloseCalled = false;
+ testMiChannel.close();
+ assertTrue(testMiChannel.isImplCloseCalled);
+ assertFalse(testMiChannel.isOpen());
+ }
+
+ /**
+ * @tests AbstractInterruptibleChannel#begin/end()
+ */
+ public void test_begin_end() throws IOException {
+ boolean complete = false;
+ MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+
+ try {
+ testChannel.superBegin();
+ complete = false;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+
+ testChannel.superBegin();
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertTrue(testChannel.isOpen());
+ testChannel.close();
+ }
+
+ /**
+ * @tests AbstractInterruptibleChannel#close/begin/end()
+ */
+ public void test_close_begin_end() throws IOException {
+ boolean complete = false;
+ MockInterruptibleChannel testChannel = new MockInterruptibleChannel();
+ assertTrue(testChannel.isOpen());
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertTrue(testChannel.isOpen());
+ testChannel.close();
+ try {
+ testChannel.superBegin();
+ complete = false;
+ } finally {
+ try {
+ testChannel.superEnd(complete);
+ fail("should throw AsynchronousCloseException");
+ } catch (AsynchronousCloseException e) {
+ // expected
+ }
+ }
+ assertFalse(testChannel.isOpen());
+ try {
+ testChannel.superBegin();
+ complete = true;
+ } finally {
+ testChannel.superEnd(complete);
+ }
+ assertFalse(testChannel.isOpen());
+ }
+
+ private class MockInterruptibleChannel extends AbstractInterruptibleChannel {
+
+ private boolean isImplCloseCalled = false;
+
+ public MockInterruptibleChannel() {
+ super();
+ }
+
+ protected void implCloseChannel() throws IOException {
+ isImplCloseCalled = true;
+ }
+
+ // call super.begin() for test
+ void superBegin() {
+ super.begin();
+ }
+
+ // call super.end() for test
+ void superEnd(boolean completed) throws AsynchronousCloseException {
+ super.end(completed);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
new file mode 100644
index 0000000..b396264
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectableChannelTest.java
@@ -0,0 +1,313 @@
+/* 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.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.IllegalSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelectableChannel
+ */
+public class AbstractSelectableChannelTest extends TestCase {
+
+ private MockSelectableChannel testChannel;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testChannel = new MockSelectableChannel(SelectorProvider.provider());
+ }
+
+ protected void tearDown() throws Exception {
+ if (testChannel.isOpen()) {
+ testChannel.close();
+ }
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#implCloseChannel()
+ */
+ public void test_implClose() throws IOException {
+ testChannel.isImplCloseSelectableChannelCalled = false;
+ testChannel.implCloseSelectableChannelCount = 0;
+ testChannel.close();
+ assertFalse(testChannel.isOpen());
+ assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+ assertEquals(1, testChannel.implCloseSelectableChannelCount);
+
+ testChannel = new MockSelectableChannel(SelectorProvider.provider());
+ testChannel.isImplCloseSelectableChannelCalled = false;
+ testChannel.implCloseSelectableChannelCount = 0;
+ // close twice.
+ // make sure implCloseSelectableChannelCount is called only once.
+ testChannel.close();
+ testChannel.close();
+ assertFalse(testChannel.isOpen());
+ assertTrue(testChannel.isImplCloseSelectableChannelCalled);
+ assertEquals(1, testChannel.implCloseSelectableChannelCount);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#provider()
+ */
+ public void test_provider() {
+ SelectorProvider provider = testChannel.provider();
+ assertSame(SelectorProvider.provider(), provider);
+ testChannel = new MockSelectableChannel(null);
+ provider = testChannel.provider();
+ assertNull(provider);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#isBlocking()
+ */
+ public void test_isBlocking() throws IOException {
+ assertTrue(testChannel.isBlocking());
+ testChannel.configureBlocking(false);
+ assertFalse(testChannel.isBlocking());
+ testChannel.configureBlocking(true);
+ assertTrue(testChannel.isBlocking());
+ }
+
+ /**
+ *
+ * @tests AbstractSelectableChannel#blockingLock()
+ */
+ public void test_blockingLock() {
+ Object gotObj = testChannel.blockingLock();
+ assertNotNull(gotObj);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#register(Selector, int, Object)
+ */
+ public void test_register_LSelectorILObject() throws IOException {
+ assertFalse(testChannel.isRegistered());
+ Selector acceptSelector1 = SelectorProvider.provider().openSelector();
+ Selector acceptSelector2 = new MockAbstractSelector(SelectorProvider
+ .provider());
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ SelectionKey acceptKey = sc.register(acceptSelector1,
+ SelectionKey.OP_READ, null);
+ assertNotNull(acceptKey);
+ assertTrue(acceptKey.isValid());
+ assertSame(sc, acceptKey.channel());
+
+ //test that sc.register invokes Selector.register()
+ acceptKey = sc.register(acceptSelector2, SelectionKey.OP_READ, null);
+ assertNull(acceptKey);
+
+ // Regression test to ensure acceptance of a selector with empty
+ // interest set.
+ SocketChannel channel = SocketChannel.open();
+ channel.configureBlocking(false);
+ Selector selector = Selector.open();
+ channel.register(selector, 0);
+ selector.close();
+ channel.close();
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#register(Selector, int, Object)
+ */
+ public void test_register_LSelectorILObject_IllegalArgument()
+ throws IOException {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ assertTrue(acceptSelector.isOpen());
+ MockSelectableChannel msc = new MockSelectableChannel(SelectorProvider
+ .provider());
+ msc.configureBlocking(false);
+ // in nonblocking mode
+ try {
+ //different SelectionKey with validOps
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ // in nonblocking mode, if selector closed
+ acceptSelector.close();
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ try {
+ msc.register(acceptSelector, 0, null);
+ fail("Should throw IllegalSelectorException");
+ } catch (IllegalSelectorException e) {
+ // expected
+ }
+
+ acceptSelector = SelectorProvider.provider().openSelector();
+ // test in blocking mode
+ msc.configureBlocking(true);
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ acceptSelector.close();
+ // in blocking mode, if selector closed
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ try {
+ msc.register(null, 0, null);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+
+ // register with an object
+ Object argObj = new Object();
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ try {
+ sc.register(null, SelectionKey.OP_READ, argObj);
+ fail("Should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+
+ // if channel closed
+ msc.close();
+ try {
+ msc.register(acceptSelector, SelectionKey.OP_READ, null);
+ fail("Should throw ClosedChannelException");
+ } catch (ClosedChannelException e) {
+ // expected
+ }
+
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#keyFor(Selector)
+ */
+ public void test_keyfor_LSelector() throws Exception {
+ SocketChannel sc = SocketChannel.open();
+ Object argObj = new Object();
+ sc.configureBlocking(false);
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ Selector acceptSelectorOther = SelectorProvider.provider()
+ .openSelector();
+ SelectionKey acceptKey = sc.register(acceptSelector,
+ SelectionKey.OP_READ, argObj);
+ assertEquals(sc.keyFor(acceptSelector), acceptKey);
+ SelectionKey acceptKeyObjNull = sc.register(acceptSelector,
+ SelectionKey.OP_READ, null);
+ assertSame(sc.keyFor(acceptSelector), acceptKeyObjNull);
+ assertSame(acceptKeyObjNull, acceptKey);
+ SelectionKey acceptKeyOther = sc.register(acceptSelectorOther,
+ SelectionKey.OP_READ, null);
+ assertSame(sc.keyFor(acceptSelectorOther), acceptKeyOther);
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#configureBlocking(boolean)
+ */
+ public void test_configureBlocking_Z_IllegalBlockingMode() throws Exception {
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ SelectionKey acceptKey = sc.register(acceptSelector,
+ SelectionKey.OP_READ, null);
+ assertEquals(sc.keyFor(acceptSelector), acceptKey);
+ SelectableChannel getChannel = sc.configureBlocking(false);
+ assertEquals(getChannel, sc);
+ try {
+ sc.configureBlocking(true);
+ fail("Should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests AbstractSelectableChannel#configureBlocking(boolean)
+ */
+ public void test_configureBlocking_Z() throws Exception {
+ MockSelectableChannel mock = new MockSelectableChannel(SelectorProvider
+ .provider());
+ //default blocking mode is true
+ //the implConfigureBlocking is only invoked if the given mode is different with current one
+ mock.configureBlocking(true);
+ assertFalse(mock.implConfigureBlockingCalled);
+ mock.configureBlocking(false);
+ assertTrue(mock.implConfigureBlockingCalled);
+ }
+
+ private class MockSelectableChannel extends AbstractSelectableChannel {
+
+ private boolean isImplCloseSelectableChannelCalled = false;
+
+ private int implCloseSelectableChannelCount = 0;
+
+ private boolean implConfigureBlockingCalled = false;
+
+ public MockSelectableChannel(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ protected void implCloseSelectableChannel() throws IOException {
+ isImplCloseSelectableChannelCalled = true;
+ ++implCloseSelectableChannelCount;
+ }
+
+ protected void implConfigureBlocking(boolean arg0) throws IOException {
+ implConfigureBlockingCalled = true;
+ }
+
+ public int validOps() {
+ return SelectionKey.OP_ACCEPT;
+ }
+
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
new file mode 100644
index 0000000..1404fc1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectionKeyTest.java
@@ -0,0 +1,76 @@
+/* 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.tests.java.nio.channels.spi;
+
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectionKey;
+
+import junit.framework.TestCase;
+
+public class AbstractSelectionKeyTest extends TestCase {
+
+ /**
+ * @tests AbstractSelectionKey#isValid() without selector
+ */
+ public void test_isValid() throws Exception {
+ MockSelectionKey testKey = new MockSelectionKey();
+ assertTrue(testKey.isValid());
+ }
+
+ /**
+ * @tests AbstractSelectionKey#cancel
+ */
+ public void test_cancel() throws Exception {
+ MockSelectionKey testKey = new MockSelectionKey();
+ try {
+ testKey.cancel();
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected: no selector available
+ }
+ assertFalse(testKey.isValid());
+ }
+
+ private class MockSelectionKey extends AbstractSelectionKey {
+
+ MockSelectionKey() {
+ super();
+ }
+
+ public SelectableChannel channel() {
+ return null;
+ }
+
+ public Selector selector() {
+ return null;
+ }
+
+ public int interestOps() {
+ return 0;
+ }
+
+ public SelectionKey interestOps(int arg0) {
+ return null;
+ }
+
+ public int readyOps() {
+ return 0;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
new file mode 100644
index 0000000..4b39001
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/AbstractSelectorTest.java
@@ -0,0 +1,160 @@
+/* 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.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.IllegalBlockingModeException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.spi.SelectorProvider;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for AbstractSelector and register of its default implementation
+ */
+public class AbstractSelectorTest extends TestCase {
+
+ /**
+ * @tests AbstractSelector#provider()
+ */
+ public void test_provider() throws IOException {
+ Selector mockSelector = new MockAbstractSelector(SelectorProvider
+ .provider());
+ assertTrue(mockSelector.isOpen());
+ assertSame(SelectorProvider.provider(), mockSelector.provider());
+ mockSelector = new MockAbstractSelector(null);
+ assertNull(mockSelector.provider());
+ }
+
+ /**
+ * @tests AbstractSelector#close()
+ */
+ public void test_close() throws IOException {
+ MockAbstractSelector mockSelector = new MockAbstractSelector(
+ SelectorProvider.provider());
+ mockSelector.close();
+ assertTrue(mockSelector.isImplCloseSelectorCalled);
+ }
+
+ /**
+ *
+ * @tests AbstractSelector#begin/end()
+ */
+ public void test_begin_end() throws IOException {
+ MockAbstractSelector mockSelector = new MockAbstractSelector(
+ SelectorProvider.provider());
+ try {
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ mockSelector = new MockAbstractSelector(SelectorProvider.provider());
+ try {
+ mockSelector.superBegin();
+ mockSelector.close();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ try {
+ // begin twice
+ mockSelector.superBegin();
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+
+ try {
+ mockSelector.superBegin();
+ } finally {
+ // end twice
+ mockSelector.superEnd();
+ mockSelector.superEnd();
+ }
+
+ mockSelector.close();
+ try {
+ mockSelector.superBegin();
+ } finally {
+ mockSelector.superEnd();
+ }
+ }
+
+ /**
+ * @tests AbstractSelector#isOpen()
+ */
+ public void test_isOpen() throws Exception {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ assertTrue(acceptSelector.isOpen());
+ acceptSelector.close();
+ assertFalse(acceptSelector.isOpen());
+ }
+
+ /**
+ * @tests AbstractSelector#register(Selector,int)
+ */
+ public void test_register_LSelectorI() throws Exception {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+
+ assertFalse(ssc.isRegistered());
+ SelectionKey acceptKey = ssc.register(acceptSelector,
+ SelectionKey.OP_ACCEPT);
+ assertTrue(ssc.isRegistered());
+ assertNotNull(acceptKey);
+ assertTrue(acceptSelector.keys().contains(acceptKey));
+ }
+
+ /**
+ * @tests AbstractSelector#register(Selector,int)
+ */
+ public void test_register_LSelectorI_error() throws IOException {
+ Selector acceptSelector = SelectorProvider.provider().openSelector();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+ ssc.configureBlocking(false);
+ acceptSelector.close();
+
+ assertFalse(acceptSelector.isOpen());
+ try {
+ ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+ fail("should throw NullPointerException");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ assertFalse(ssc.isRegistered());
+
+ acceptSelector = Selector.open();
+ ssc.configureBlocking(true);
+ try {
+ ssc.register(acceptSelector, SelectionKey.OP_ACCEPT);
+ fail("should throw IllegalBlockingModeException");
+ } catch (IllegalBlockingModeException e) {
+ // expected
+ }
+ assertFalse(ssc.isRegistered());
+ ssc.configureBlocking(false);
+ SelectionKey acceptKey = ssc.register(acceptSelector,
+ SelectionKey.OP_ACCEPT);
+ assertNotNull(acceptKey);
+ assertTrue(acceptSelector.keys().contains(acceptKey));
+ assertTrue(ssc.isRegistered());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
new file mode 100644
index 0000000..6e016b0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio/tests/java/nio/channels/spi/MockAbstractSelector.java
@@ -0,0 +1,89 @@
+/* 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.tests.java.nio.channels.spi;
+
+import java.io.IOException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.AbstractSelectableChannel;
+import java.nio.channels.spi.AbstractSelectionKey;
+import java.nio.channels.spi.AbstractSelector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.Set;
+
+public class MockAbstractSelector extends AbstractSelector {
+
+ public boolean isImplCloseSelectorCalled = false;
+
+ public MockAbstractSelector(SelectorProvider arg0) {
+ super(arg0);
+ }
+
+ public static MockAbstractSelector openSelector() {
+ return new MockAbstractSelector(SelectorProvider.provider());
+ }
+
+ public Set getCancelledKeys() {
+ return super.cancelledKeys();
+ }
+
+ protected void implCloseSelector() throws IOException {
+ isImplCloseSelectorCalled = true;
+ }
+
+ protected SelectionKey register(AbstractSelectableChannel arg0, int arg1,
+ Object arg2) {
+ return null;
+ }
+
+ public void superBegin() {
+ super.begin();
+ }
+
+ public void superEnd() {
+ super.end();
+ }
+
+ protected void mockDeregister(AbstractSelectionKey key) {
+ super.deregister(key);
+ }
+
+ public Set<SelectionKey> keys() {
+ return null;
+ }
+
+ public Set<SelectionKey> selectedKeys() {
+ return null;
+ }
+
+ public int selectNow() throws IOException {
+ return 0;
+ }
+
+ public int select(long arg0) throws IOException {
+ return 0;
+ }
+
+ public int select() throws IOException {
+ return 0;
+ }
+
+ public Selector wakeup() {
+ return null;
+ }
+
+}
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
new file mode 100644
index 0000000..6f59190
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/ASCIICharsetEncoderTest.java
@@ -0,0 +1,453 @@
+/* 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.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+public class ASCIICharsetEncoderTest extends TestCase {
+
+ // charset for ascii
+ private static final Charset cs = Charset.forName("ascii");
+ private static final CharsetEncoder encoder = cs.newEncoder();
+ private static final int MAXCODEPOINT = 0x7F;
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for ascCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertFalse(encoder.canEncode("\uc2a3"));
+ assertFalse(encoder.canEncode("\ud800\udc00"));
+ try {
+ encoder.canEncode(null);
+ } catch (NullPointerException e) {
+ }
+ assertTrue(encoder.canEncode(""));
+ }
+
+ public void testCanEncodeSurrogate () {
+ assertFalse(encoder.canEncode('\ud800'));
+ assertFalse(encoder.canEncode("\udc00"));
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ assertTrue(encoder.canEncode('\u0077'));
+ assertFalse(encoder.canEncode('\uc2a3'));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(1.0, encoder.averageBytesPerChar(), 0.0);
+ assertEquals(1.0, encoder.maxBytesPerChar(), 0.0);
+ }
+
+ public void testMultiStepEncode() throws CharacterCodingException {
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ try {
+ encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+ fail("should unmappable");
+ } catch (UnmappableCharacterException e) {
+ }
+ encoder.reset();
+ ByteBuffer out = ByteBuffer.allocate(10);
+ assertTrue(encoder.encode(CharBuffer.wrap("\ud800"), out, true)
+ .isMalformed());
+ encoder.flush(out);
+ encoder.reset();
+ out = ByteBuffer.allocate(10);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(CharBuffer
+ .wrap("\ud800"), out, false));
+ assertTrue(encoder.encode(CharBuffer.wrap("\udc00"), out, true)
+ .isMalformed());
+ }
+
+ 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);
+ } catch (MalformedInputException e) {
+ //expected
+ }
+
+ ByteBuffer bb = ByteBuffer.allocate(0x10);
+ cb = CharBuffer.wrap("A");
+ encoder.reset();
+ encoder.encode(cb, bb, false);
+ try {
+ encoder.encode(cb);
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+
+ public void testInternalState() {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+
+ //normal encoding process
+ encoder.reset();
+ encoder.encode(in, out, false);
+ in = CharBuffer.wrap("B");
+ 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();
+
+ //encoding - >reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ newEncoder.reset();
+ }
+
+ //encoding end -> reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.reset();
+ }
+ //flused -> reset
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ newEncoder.reset();
+ }
+ }
+
+ public void testInternalState_Encoding() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+ //Init - > encoding
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ 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.encode(in, out, false);
+ }
+ //reset - > encoding - > encoding
+ {
+ 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();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ //flushed - > encoding
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ }
+
+ public void testInternalState_Encoding_END() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+
+ //Init - >encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ }
+
+ //Reset -> encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.reset();
+ newEncoder.encode(in, out, true);
+ }
+
+ //encoding -> encoding_end
+ {
+ 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, true);
+ }
+
+ //Reset -> encoding_end
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in, out, true);
+ }
+
+ //Flushed -> encoding_end
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ in = CharBuffer.wrap("BC");
+ try {
+ newEncoder.encode(in, out, true);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+ }
+
+ public void testInternalState_Flushed() {
+ CharsetEncoder newEncoder = cs.newEncoder();
+
+ // init -> flushed
+ {
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ try {
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+
+ }
+
+ // reset - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.reset();
+ try {
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ }
+
+ //encoding - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ try {
+
+ newEncoder.flush(out);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ //encoding_end -> flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ newEncoder.flush(out);
+ }
+
+ //flushd - > flushed
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ 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
+ }
+ }
+ }
+
+ public void testInternalState_Encode() throws CharacterCodingException {
+ CharsetEncoder newEncoder = cs.newEncoder();
+ //Init - > encode
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ }
+
+ //Reset - > encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ }
+
+ //Encoding -> encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, false);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+
+ //Encoding_end -> encode
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+
+ //Flushed -> reset
+ {
+ newEncoder.reset();
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ in = CharBuffer.wrap("BC");
+ newEncoder.flush(out);
+ 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");
+ newEncoder.encode(in);
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ try {
+ newEncoder.encode(in, out, false);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // expected
+ }
+ }
+
+ //Encode -> Encoding_end
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ ByteBuffer out = ByteBuffer.allocate(0x10);
+ newEncoder.encode(in, out, true);
+ }
+
+ //Encode -> Flushed
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ ByteBuffer out = newEncoder.encode(in);
+ newEncoder.flush(out);
+ }
+
+ //Encode - > encode
+ {
+ CharBuffer in = CharBuffer.wrap("A");
+ newEncoder.encode(in);
+ in = CharBuffer.wrap("BC");
+ newEncoder.encode(in);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
new file mode 100644
index 0000000..a45938f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharacterCodingExceptionTest.java
@@ -0,0 +1,53 @@
+/* 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.io.IOException;
+import java.nio.charset.CharacterCodingException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test CharacterCodingException
+ */
+public class CharacterCodingExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ CharacterCodingException ex = new CharacterCodingException();
+ assertTrue(ex instanceof IOException);
+ assertNull(ex.getCause());
+ assertNull(ex.getMessage());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CharacterCodingException());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ SerializationTest.verifyGolden(this, new CharacterCodingException());
+
+ }
+}
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
new file mode 100644
index 0000000..4ed4ab9
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,280 @@
+/* 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.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class CharsetDecoderTest extends TestCase {
+
+ /**
+ * @tests java.nio.charset.CharsetDecoder.CharsetDecoder(Charset, float,
+ * float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetFF() {
+ // Regression for HARMONY-142
+ try {
+ Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+ new MockCharsetDecoderForHarmony142(cs, 1.1f, 1);
+ fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /*
+ * MockCharsetDecoderForHarmony142: for constructor test
+ */
+ static class MockCharsetDecoderForHarmony142 extends CharsetDecoder {
+ protected MockCharsetDecoderForHarmony142(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar) {
+ super(cs, averageBytesPerChar, maxBytesPerChar);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ return null;
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.CharsetDecoder#decode(java.nio.ByteBuffer)
+ */
+ public void test_decode() throws CharacterCodingException {
+ // Regression for HARMONY-33
+// ByteBuffer bb = ByteBuffer.allocate(1);
+// bb.put(0, (byte) 77);
+// CharsetDecoder decoder = Charset.forName("UTF-16").newDecoder();
+// decoder.onMalformedInput(CodingErrorAction.REPLACE);
+// decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+// decoder.decode(bb);
+
+ // Regression for HARMONY-67
+// byte[] b = new byte[] { (byte) 1 };
+// ByteBuffer buf = ByteBuffer.wrap(b);
+// CharBuffer charbuf = Charset.forName("UTF-16").decode(buf);
+// assertEquals("Assert 0: charset UTF-16", 1, charbuf.length());
+//
+// charbuf = Charset.forName("UTF-16BE").decode(buf);
+// assertEquals("Assert 1: charset UTF-16BE", 0, charbuf.length());
+//
+// 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);
+ decoder2.onUnmappableCharacter(CodingErrorAction.REPORT);
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 109, 97, 109 });
+ try {
+ decoder2.decode(in);
+ fail("Assert 3: MalformedInputException should have thrown");
+ } catch (MalformedInputException e) {
+ //expected
+ }
+ }
+
+ /*
+ * Test malfunction decode(ByteBuffer)
+ */
+ public void test_decodeLjava_nio_ByteBuffer() throws Exception {
+ MockMalfunctionCharset cs1 = new MockMalfunctionCharset(
+ "Harmony-124-1", null); //$NON-NLS-1$
+ try {
+ cs1.newDecoder().onMalformedInput(CodingErrorAction.REPLACE)
+ .onUnmappableCharacter(CodingErrorAction.REPLACE).decode(
+ ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+ fail("Assert 0: should throw CoderMalfunctionError"); // NON-NLS-1$
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+
+ MockMalfunctionCharset cs2 = new MockMalfunctionCharset(
+ "Harmony-124-2", null); //$NON-NLS-1$
+ try {
+ cs2.decode(ByteBuffer.wrap(new byte[] { 0x00, 0x11 }));
+ fail("Assert 1: Charset.decode should throw CoderMalfunctionError"); // NON-NLS-1
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+ }
+
+ /*
+ * Mock charset class with malfunction decode & encode.
+ */
+ static final class MockMalfunctionCharset extends Charset {
+
+ public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new MockMalfunctionDecoder(this);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockMalfunctionEncoder(this);
+ }
+ }
+
+ /*
+ * Mock decoder. decodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionDecoder extends java.nio.charset.CharsetDecoder {
+
+ public MockMalfunctionDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Mock encoder. encodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+ public MockMalfunctionEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Test the method decode(ByteBuffer) .
+ */
+ public void testDecodeLjava_nio_ByteBuffer_ReplaceOverflow()
+ throws Exception {
+ String replaceString = "a";
+ Charset cs = Charset.forName("UTF-8");
+ MockMalformedDecoder decoder = new MockMalformedDecoder(cs);
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ decoder.replaceWith(replaceString);
+ CharBuffer out = CharBuffer.allocate(1);
+ // MockMalformedDecoder treats the second byte '0x38' as malformed,
+ // but "out" doesn't have enough space for replace string.
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 0x45, 0x38, 0x45, 0x45 });
+ CoderResult result = decoder.decode(in, out, false);
+ assertTrue(result.isOverflow());
+
+ // allocate enough space for "out"
+ out = CharBuffer.allocate(10);
+ // replace string should be put into "out" firstly,
+ // and then decode "in".
+ result = decoder.decode(in, out, true);
+ out.flip();
+ assertTrue(result.isUnderflow());
+ assertEquals("bb", out.toString());
+ }
+
+ /*
+ * Mock decoder. It treats byte whose value is less than "0x40" as
+ * malformed.
+ */
+ static class MockMalformedDecoder extends java.nio.charset.CharsetDecoder {
+
+ public MockMalformedDecoder(Charset cs) {
+ super(cs, 1, 10);
+ }
+
+ /*
+ * It treats byte whose value is less than "0x40" as malformed.
+ * Otherwise, it's decoded as 'b'.
+ */
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ while (in.hasRemaining()) {
+ byte b = in.get();
+ if (b < 0x40) {
+ return CoderResult.malformedForLength(1);
+ }
+ if (!out.hasRemaining()) {
+ return CoderResult.OVERFLOW;
+ }
+ out.put((char) 'b');
+ }
+ return CoderResult.UNDERFLOW;
+ }
+ }
+
+
+ public void testInvalidDecoding() throws IOException {
+
+ byte[][] invalidSequences = new byte[][] {
+ // overlong NULL
+ { (byte) 0xC0, (byte) 0x80 },
+ // overlong ascii 'A'
+ { (byte) 0xC0, (byte) 0xC1 },
+ // overlong "/../"
+ { (byte) 0x2F, (byte) 0xC0, (byte) 0xAE, (byte) 0x2E, (byte) 0x2F },
+ // Invalid encoding 2r11111000 (sequence too long)
+ { (byte) 0xF8 },
+ // Invalid encoding 2r10000000 (sequence too short)
+ { (byte) 0x80 }
+ };
+
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+ decoder.onMalformedInput(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
+ }
+ }
+
+ /*
+ * When bytebuffer has _not_ got a backing array...
+ */
+ for (byte[] bytes : invalidSequences) {
+ 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
+ }
+ }
+ }
+
+}
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
new file mode 100644
index 0000000..dd514da
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,202 @@
+/* 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.io.IOException;
+import java.nio.BufferOverflowException;
+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.CoderMalfunctionError;
+import java.nio.charset.CoderResult;
+
+import junit.framework.TestCase;
+
+public class CharsetEncoderTest extends TestCase {
+
+ /**
+ * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+ * java.nio.charset.Charset, float, float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetFF() {
+ // Regression for HARMONY-141
+ try {
+ Charset cs = Charset.forName("UTF-8"); //$NON-NLS-1$
+ new MockCharsetEncoderForHarmony141(cs, 1.1f, 1);
+ fail("Assert 0: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+
+ try {
+ Charset cs = Charset.forName("ISO8859-1"); //$NON-NLS-1$
+ new MockCharsetEncoderForHarmony141(cs, 1.1f, 1,
+ new byte[] { 0x1a });
+ fail("Assert 1: Should throw IllegalArgumentException."); //$NON-NLS-1$
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests java.nio.charset.CharsetEncoder.CharsetEncoder(
+ * java.nio.charset.Charset, float, float)
+ */
+ public void test_ConstructorLjava_nio_charset_CharsetNull() {
+ // Regression for HARMONY-491
+ CharsetEncoder ech = new MockCharsetEncoderForHarmony491(null, 1, 1);
+ assertNull(ech.charset());
+ }
+
+ /**
+ * Helper for constructor tests
+ */
+
+ public static class MockCharsetEncoderForHarmony141 extends CharsetEncoder {
+
+ protected MockCharsetEncoderForHarmony141(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar) {
+ super(cs, averageBytesPerChar, maxBytesPerChar);
+ }
+
+ public MockCharsetEncoderForHarmony141(Charset cs,
+ float averageBytesPerChar, float maxBytesPerChar,
+ byte[] replacement) {
+ super(cs, averageBytesPerChar, maxBytesPerChar, replacement);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ return null;
+ }
+ }
+
+ public static class MockCharsetEncoderForHarmony491 extends CharsetEncoder {
+
+ public MockCharsetEncoderForHarmony491(Charset arg0, float arg1,
+ float arg2) {
+ super(arg0, arg1, arg2);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer arg0, ByteBuffer arg1) {
+ return null;
+ }
+
+ public boolean isLegalReplacement(byte[] arg0) {
+ return true;
+ }
+ }
+
+ /*
+ * Test malfunction encode(CharBuffer)
+ */
+ public void test_EncodeLjava_nio_CharBuffer() throws Exception {
+ MockMalfunctionCharset cs = new MockMalfunctionCharset("mock", null);
+ try {
+ cs.encode(CharBuffer.wrap("AB"));
+ fail("should throw CoderMalfunctionError");// NON-NLS-1$
+ } catch (CoderMalfunctionError e) {
+ // expected
+ }
+ }
+
+ /*
+ * Mock charset class with malfunction decode & encode.
+ */
+ static final class MockMalfunctionCharset extends Charset {
+
+ public MockMalfunctionCharset(String canonicalName, String[] aliases) {
+ super(canonicalName, aliases);
+ }
+
+ public boolean contains(Charset cs) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return Charset.forName("UTF-8").newDecoder();
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockMalfunctionEncoder(this);
+ }
+ }
+
+ /*
+ * Mock encoder. encodeLoop always throws unexpected exception.
+ */
+ static class MockMalfunctionEncoder extends java.nio.charset.CharsetEncoder {
+
+ public MockMalfunctionEncoder(Charset cs) {
+ super(cs, 1, 3, new byte[] { (byte) '?' });
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ throw new BufferOverflowException();
+ }
+ }
+
+ /*
+ * Test reserve bytes encode(CharBuffer,ByteBuffer,boolean)
+ */
+ 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);
+ encoder.reset();
+
+ // If we supply just the high surrogate...
+ CoderResult result = encoder.encode(in1, out, false);
+ // ...we're not done...
+ assertTrue(result.isUnderflow());
+ assertEquals(4, out.remaining());
+ // ...but if we then supply the low surrogate...
+ result = encoder.encode(in2, out, true);
+ // ...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());
+
+ // 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);
+ assertEquals(0xd800, chars.get(0));
+ assertEquals(0xdc00, chars.get(1));
+ }
+
+ /**
+ * @tests {@link java.nio.charset.Charset#encode(java.nio.CharBuffer)
+ */
+ public void testUtf8Encoding() throws IOException {
+ byte[] orig = new byte[] { (byte) 0xed, (byte) 0xa0,
+ (byte) 0x80 };
+ String s = new String(orig, "UTF-8");
+ assertEquals(1, s.length());
+ assertEquals(55296, s.charAt(0));
+ Charset.forName("UTF-8").encode(CharBuffer.wrap(s));
+// ByteBuffer buf = <result>
+// for (byte o : orig) {
+// byte b = 0;
+// buf.get(b);
+// assertEquals(o, b);
+// }
+ }
+
+}
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
new file mode 100644
index 0000000..134bea6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CharsetTest.java
@@ -0,0 +1,245 @@
+/* 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/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
new file mode 100644
index 0000000..8e6318f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/CoderMalfunctionErrorTest.java
@@ -0,0 +1,62 @@
+/* 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.charset.CoderMalfunctionError;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+
+/**
+ * Test java.nio.CoderMalfunctionError.
+ */
+public class CoderMalfunctionErrorTest extends TestCase {
+
+ /*
+ * Test constructor with normal param.
+ */
+ public void testConstructor_Normal() {
+ Exception ex = new Exception();
+ CoderMalfunctionError e = new CoderMalfunctionError(ex);
+ assertSame(ex, e.getCause());
+ }
+
+ /*
+ * Test constructor with null param.
+ */
+ public void testConstructor_Null() {
+ CoderMalfunctionError e = new CoderMalfunctionError(null);
+ assertNull(e.getCause());
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new CoderMalfunctionError(null));
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ SerializationTest.verifyGolden(this, new CoderMalfunctionError(null));
+
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
new file mode 100644
index 0000000..a514aef
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/IllegalCharsetNameExceptionTest.java
@@ -0,0 +1,94 @@
+/* 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.io.Serializable;
+import java.nio.charset.IllegalCharsetNameException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class IllegalCharsetNameException.
+ */
+public class IllegalCharsetNameExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ IllegalCharsetNameException ex = new IllegalCharsetNameException(
+ "impossible");
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "impossible");
+ assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+ ex = new IllegalCharsetNameException("ascii");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "ascii");
+ assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+ ex = new IllegalCharsetNameException("");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "");
+ ex.getMessage();
+
+ ex = new IllegalCharsetNameException(null);
+ assertNull(ex.getCause());
+ assertNull(ex.getCharsetName());
+ assertTrue(ex.getMessage().indexOf("null") != -1);
+
+ }
+
+ // comparator for IllegalCharsetNameException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // FIXME?: getMessage() returns more helpful string but
+ // this leads to incompatible message in serial form
+ //
+ // do common checks for all throwable objects
+ // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ // deserialized);
+
+ IllegalCharsetNameException initEx = (IllegalCharsetNameException) initial;
+ IllegalCharsetNameException desrEx = (IllegalCharsetNameException) deserialized;
+
+ assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+ .getCharsetName());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new IllegalCharsetNameException(
+ "charsetName"), COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new IllegalCharsetNameException(
+ "charsetName"), COMPARATOR);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
new file mode 100644
index 0000000..f482d9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/MalformedInputExceptionTest.java
@@ -0,0 +1,85 @@
+/* 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.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.MalformedInputException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class MalformedInputException.
+ */
+public class MalformedInputExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ MalformedInputException ex = new MalformedInputException(3);
+ assertTrue(ex instanceof CharacterCodingException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 3);
+ assertTrue(ex.getMessage().indexOf("3") != -1);
+
+ ex = new MalformedInputException(-3);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), -3);
+ assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+ ex = new MalformedInputException(0);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 0);
+ assertTrue(ex.getMessage().indexOf("0") != -1);
+ }
+
+ // comparator for MalformedInputException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ MalformedInputException initEx = (MalformedInputException) initial;
+ MalformedInputException desrEx = (MalformedInputException) deserialized;
+
+ assertEquals("InputLength", initEx.getInputLength(), desrEx
+ .getInputLength());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new MalformedInputException(11),
+ COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new MalformedInputException(11),
+ COMPARATOR);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
new file mode 100644
index 0000000..a6cf6a6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnmappableCharacterExceptionTest.java
@@ -0,0 +1,86 @@
+/* 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.io.Serializable;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnmappableCharacterException.
+ */
+public class UnmappableCharacterExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ UnmappableCharacterException ex = new UnmappableCharacterException(3);
+ assertTrue(ex instanceof CharacterCodingException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 3);
+ assertTrue(ex.getMessage().indexOf("3") != -1);
+
+ ex = new UnmappableCharacterException(-3);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), -3);
+ assertTrue(ex.getMessage().indexOf("-3") != -1);
+
+ ex = new UnmappableCharacterException(0);
+ assertNull(ex.getCause());
+ assertEquals(ex.getInputLength(), 0);
+ assertTrue(ex.getMessage().indexOf("0") != -1);
+
+ }
+
+ // comparator for UnmappableCharacterException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ UnmappableCharacterException initEx = (UnmappableCharacterException) initial;
+ UnmappableCharacterException desrEx = (UnmappableCharacterException) deserialized;
+
+ assertEquals("InputLength", initEx.getInputLength(), desrEx
+ .getInputLength());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnmappableCharacterException(11),
+ COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnmappableCharacterException(
+ 11), COMPARATOR);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
new file mode 100644
index 0000000..57ea31c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/nio_char/tests/java/nio/charset/UnsupportedCharsetExceptionTest.java
@@ -0,0 +1,93 @@
+/* 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.io.Serializable;
+import java.nio.charset.UnsupportedCharsetException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+/**
+ * Test class UnsupportedCharsetException.
+ */
+public class UnsupportedCharsetExceptionTest extends TestCase {
+
+ public void testConstructor() {
+ UnsupportedCharsetException ex = new UnsupportedCharsetException(
+ "impossible");
+ assertTrue(ex instanceof IllegalArgumentException);
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "impossible");
+ assertTrue(ex.getMessage().indexOf("impossible") != -1);
+
+ ex = new UnsupportedCharsetException("ascii");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "ascii");
+ assertTrue(ex.getMessage().indexOf("ascii") != -1);
+
+ ex = new UnsupportedCharsetException("");
+ assertNull(ex.getCause());
+ assertEquals(ex.getCharsetName(), "");
+ ex.getMessage();
+
+ ex = new UnsupportedCharsetException(null);
+ assertNull(ex.getCause());
+ assertNull(ex.getCharsetName());
+ assertTrue(ex.getMessage().indexOf("null") != -1);
+ }
+
+ // comparator for UnsupportedCharsetException objects
+ private static final SerializableAssert COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // FIXME?: getMessage() returns more helpful string but
+ // this leads to incompatible message in serial form
+ //
+ // do common checks for all throwable objects
+ // SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ // deserialized);
+
+ UnsupportedCharsetException initEx = (UnsupportedCharsetException) initial;
+ UnsupportedCharsetException desrEx = (UnsupportedCharsetException) deserialized;
+
+ assertEquals("CharsetName", initEx.getCharsetName(), desrEx
+ .getCharsetName());
+ }
+ };
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ public void testSerializationSelf() throws Exception {
+
+ SerializationTest.verifySelf(new UnsupportedCharsetException(
+ "charsetName"), COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+
+ SerializationTest.verifyGolden(this, new UnsupportedCharsetException(
+ "charsetName"), COMPARATOR);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java
new file mode 100644
index 0000000..ba71e2c
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalArithmeticTest.java
@@ -0,0 +1,1623 @@
+/*
+ * 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.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class: java.math.BigDecimal
+ * Methods: add, subtract, multiply, divide
+ */
+public class BigDecimalArithmeticTest extends TestCase {
+ /**
+ * Add two numbers of equal positive scales
+ */
+ public void testAddEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "123121247898748373566323807282924555312937.1991359555";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal positive scales using MathContext
+ */
+ public void testAddMathContextEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.2313E+41";
+ int cScale = -37;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(5, RoundingMode.UP);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal negative scales
+ */
+ public void testAddEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.231212478987483735663238072829245553129371991359555E+61";
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of equal negative scales using MathContext
+ */
+ public void testAddMathContextEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.2312E+61";
+ int cScale = -57;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(5, RoundingMode.FLOOR);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value ", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales; the first is positive
+ */
+ public void testAddDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "7472334294161400358170962860775454459810457634.781384756794987";
+ int cScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales using MathContext; the first is positive
+ */
+ public void testAddMathContextDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "7.47233429416141E+45";
+ int cScale = -31;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(15, RoundingMode.CEILING);
+ BigDecimal result = aNumber.add(bNumber, mc);
+ assertEquals("incorrect value", c, c.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two numbers of different scales; the first is negative
+ */
+ public void testAddDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1231212478987482988429808779810457634781459480137916301878791834798.7234564568";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Add two zeroes of different scales; the first is negative
+ */
+ public void testAddDiffScaleZeroZero() {
+ String a = "0";
+ int aScale = -15;
+ String b = "0";
+ int bScale = 10;
+ String c = "0E-10";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.add(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal positive scales
+ */
+ public void testSubtractEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "123121247898748224119637948679166971643339.7522230419";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal positive scales using MathContext
+ */
+ public void testSubtractMathContextEqualScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.23121247898749E+41";
+ int cScale = -27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(15, RoundingMode.CEILING);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of equal negative scales
+ */
+ public void testSubtractEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "1.231212478987482241196379486791669716433397522230419E+61";
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales; the first is positive
+ */
+ public void testSubtractDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "-7472334291698975400195996883915836900189542365.218615243205013";
+ int cScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales using MathContext;
+ * the first is positive
+ */
+ public void testSubtractMathContextDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "-7.4723342916989754E+45";
+ int cScale = -29;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(17, RoundingMode.DOWN);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales; the first is negative
+ */
+ public void testSubtractDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1231212478987482988429808779810457634781310033452057698121208165201.2765435432";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.subtract(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Subtract two numbers of different scales using MathContext;
+ * the first is negative
+ */
+ public void testSubtractMathContextDiffScaleNegPos() {
+ String a = "986798656676789766678767876078779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 40;
+ String c = "9.867986566767897666787678760787798104576347813847567949870000000000000E+71";
+ int cScale = -2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(70, RoundingMode.HALF_DOWN);
+ BigDecimal result = aNumber.subtract(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of positive scales
+ */
+ public void testMultiplyScalePosPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "92000312286217574978643009574114545567010139156902666284589309.1880727173060570190220616";
+ int cScale = 25;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of positive scales using MathContext
+ */
+ public void testMultiplyMathContextScalePosPos() {
+ String a = "97665696756578755423325476545428779810457634781384756794987";
+ int aScale = -25;
+ String b = "87656965586786097685674786576598865";
+ int bScale = 10;
+ String c = "8.561078619600910561431314228543672720908E+108";
+ int cScale = -69;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(40, RoundingMode.HALF_DOWN);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of negative scales
+ */
+ public void testMultiplyEqualScaleNegNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+111";
+ int cScale = -25;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales
+ */
+ public void testMultiplyDiffScalePosNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -10;
+ String c = "920003122862175749786430095741145455670101391569026662845893091880727173060570190220616";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales using MathContext
+ */
+ public void testMultiplyMathContextDiffScalePosNeg() {
+ String a = "987667796597975765768768767866756808779810457634781384756794987";
+ int aScale = 100;
+ String b = "747233429293018787918347987234564568";
+ int bScale = -70;
+ String c = "7.3801839465418518653942222612429081498248509257207477E+68";
+ int cScale = -16;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(53, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales
+ */
+ public void testMultiplyDiffScaleNegPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "9.20003122862175749786430095741145455670101391569026662845893091880727173060570190220616E+91";
+ int cScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.multiply(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Multiply two numbers of different scales using MathContext
+ */
+ public void testMultiplyMathContextDiffScaleNegPos() {
+ String a = "488757458676796558668876576576579097029810457634781384756794987";
+ int aScale = -63;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 63;
+ String c = "3.6521591193960361339707130098174381429788164316E+98";
+ int cScale = -52;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ MathContext mc = new MathContext(47, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.multiply(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(int)
+ */
+ public void testPow() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 10;
+ String c = "8004424019039195734129783677098845174704975003788210729597" +
+ "4875206425711159855030832837132149513512555214958035390490" +
+ "798520842025826.594316163502809818340013610490541783276343" +
+ "6514490899700151256484355936102754469438371850240000000000";
+ int cScale = 100;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.pow(exp);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(0)
+ */
+ public void testPow0() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 0;
+ String c = "1";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.pow(exp);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * ZERO.pow(0)
+ */
+ public void testZeroPow0() {
+ String c = "1";
+ int cScale = 0;
+ BigDecimal result = BigDecimal.ZERO.pow(0);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * pow(int, MathContext)
+ */
+ public void testPowMathContext() {
+ String a = "123121247898748298842980";
+ int aScale = 10;
+ int exp = 10;
+ String c = "8.0044E+130";
+ int cScale = -126;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
+ BigDecimal result = aNumber.pow(exp, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", cScale, result.scale());
+ }
+
+ /**
+ * Divide by zero
+ */
+ public void testDivideByZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = BigDecimal.valueOf(0L);
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Division by zero", e.getMessage());
+ }
+ }
+
+ /**
+ * Divide with ROUND_UNNECESSARY
+ */
+ public void testDivideExceptionRM() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ try {
+ aNumber.divide(bNumber, BigDecimal.ROUND_UNNECESSARY);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Rounding necessary", e.getMessage());
+ }
+ }
+
+ /**
+ * Divide with invalid rounding mode
+ */
+ public void testDivideExceptionInvalidRM() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ try {
+ aNumber.divide(bNumber, 100);
+ fail("IllegalArgumentException has not been caught");
+ } catch (IllegalArgumentException e) {
+ assertEquals("Improper exception message", "Invalid rounding mode", e.getMessage());
+ }
+ }
+
+ /**
+ * Divide: local variable exponent is less than zero
+ */
+ public void testDivideExpLessZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.64770E+10";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: local variable exponent is equal to zero
+ */
+ public void testDivideExpEqualsZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 10;
+ String c = "1.64769459009933764189139568605273529E+40";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: local variable exponent is greater than zero
+ */
+ public void testDivideExpGreaterZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -15;
+ String b = "747233429293018787918347987234564568";
+ int bScale = 20;
+ String c = "1.647694590099337641891395686052735285121058381E+50";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: remainder is zero
+ */
+ public void testDivideRemainderIsZero() {
+ String a = "8311389578904553209874735431110";
+ int aScale = -15;
+ String b = "237468273682987234567849583746";
+ int bScale = 20;
+ String c = "3.5000000000000000000000000000000E+36";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_UP, result is negative
+ */
+ public void testDivideRoundUpNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_UP, result is positive
+ */
+ public void testDivideRoundUpPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_DOWN, result is negative
+ */
+ public void testDivideRoundDownNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_DOWN, result is positive
+ */
+ public void testDivideRoundDownPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_FLOOR, result is positive
+ */
+ public void testDivideRoundFloorPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_FLOOR);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_FLOOR, result is negative
+ */
+ public void testDivideRoundFloorNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_FLOOR);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_CEILING, result is positive
+ */
+ public void testDivideRoundCeilingPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_CEILING, result is negative
+ */
+ public void testDivideRoundCeilingNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799283E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_CEILING);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = -1
+ */
+ public void testDivideRoundHalfUpPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = -1
+ */
+ public void testDivideRoundHalfUpNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is positive; distance = 1
+ */
+ public void testDivideRoundHalfUpPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; distance = 1
+ */
+ public void testDivideRoundHalfUpNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant
+ */
+ public void testDivideRoundHalfUpNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "-1E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_UP);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is positive; distance = -1
+ */
+ public void testDivideRoundHalfDownPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is negative; distance = -1
+ */
+ public void testDivideRoundHalfDownNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is positive; distance = 1
+ */
+ public void testDivideRoundHalfDownPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_DOWN, result is negative; distance = 1
+ */
+ public void testDivideRoundHalfDownNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_UP, result is negative; equidistant
+ */
+ public void testDivideRoundHalfDownNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "0E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_DOWN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = -1
+ */
+ public void testDivideRoundHalfEvenPos() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; distance = -1
+ */
+ public void testDivideRoundHalfEvenNeg() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ String c = "-1.24390557635720517122423359799284E+53";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is positive; distance = 1
+ */
+ public void testDivideRoundHalfEvenPos1() {
+ String a = "92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; distance = 1
+ */
+ public void testDivideRoundHalfEvenNeg1() {
+ String a = "-92948782094488478231212478987482988798104576347813847567949855464535634534563456";
+ int aScale = -24;
+ String b = "74723342238476237823754692930187879183479";
+ int bScale = 13;
+ String c = "-1.2439055763572051712242335979928354832010167729111113605E+76";
+ int resScale = -21;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide: rounding mode is ROUND_HALF_EVEN, result is negative; equidistant
+ */
+ public void testDivideRoundHalfEvenNeg2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "0E+5";
+ int resScale = -5;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, resScale, BigDecimal.ROUND_HALF_EVEN);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide to BigDecimal
+ */
+ public void testDivideBigDecimal1() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ String c = "-5E+4";
+ int resScale = -4;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Divide to BigDecimal
+ */
+ public void testDivideBigDecimal2() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = -15;
+ String c = "-5E-26";
+ int resScale = 26;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeUP() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = -15;
+ int newScale = 31;
+ RoundingMode rm = RoundingMode.UP;
+ String c = "-5.00000E-26";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeDOWN() {
+ String a = "-37361671119238118911893939591735";
+ int aScale = 10;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 31;
+ RoundingMode rm = RoundingMode.DOWN;
+ String c = "-50000.0000000000000000000000000000000";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeCEILING() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 100;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 45;
+ RoundingMode rm = RoundingMode.CEILING;
+ String c = "1E-45";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeFLOOR() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 100;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 45;
+ RoundingMode rm = RoundingMode.FLOOR;
+ String c = "0E-45";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -51;
+ String b = "74723342238476237823787879183470";
+ int bScale = 45;
+ int newScale = 3;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ String c = "50000260373164286401361913262100972218038099522752460421" +
+ "05959924024355721031761947728703598332749334086415670525" +
+ "3761096961.670";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 5;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 7;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ String c = "500002603731642864013619132621009722.1803810";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, scale, RoundingMode)
+ */
+ public void testDivideBigDecimalScaleRoundingModeHALF_EVEN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 5;
+ String b = "74723342238476237823787879183470";
+ int bScale = 15;
+ int newScale = 7;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ String c = "500002603731642864013619132621009722.1803810";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, newScale, rm);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", newScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "49897861180.2562512996";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextDOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512995E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextCEILING() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512996E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextFLOOR() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 15;
+ String b = "748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "4.98978611802562512995E+70";
+ int resScale = -50;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divide(BigDecimal, MathContext)
+ */
+ public void testDivideBigDecimalScaleMathContextHALF_EVEN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.77923185514690367475E+26";
+ int resScale = -6;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divide(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+
+ /**
+ * BigDecimal.divide with a scale that's too large
+ *
+ * Regression test for HARMONY-6271
+ */
+ public void testDivideLargeScale() {
+ BigDecimal arg1 = new BigDecimal("320.0E+2147483647");
+ BigDecimal arg2 = new BigDecimal("6E-2147483647");
+ try {
+ BigDecimal result = arg1.divide(arg2, Integer.MAX_VALUE,
+ java.math.RoundingMode.CEILING);
+ fail("Expected ArithmeticException when dividing with a scale that's too large");
+ } catch (ArithmeticException e) {
+ // expected behaviour
+ }
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal)
+ */
+ public void testDivideToIntegralValue() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String c = "277923185514690367474770683";
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal, MathContext)
+ */
+ public void testDivideToIntegralValueMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 32;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "277923185514690367474770683";
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divideToIntegralValue(BigDecimal, MathContext)
+ */
+ public void testDivideToIntegralValueMathContextDOWN() {
+ String a = "3736186567876876578956958769675785435673453453653543654354365435675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "2.7792318551469036747477068339450205874992634417590178670822889E+62";
+ int resScale = -1;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.divideToIntegralValue(bNumber, mc);
+ assertEquals("incorrect value", c, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal)
+ */
+ public void testDivideAndRemainder1() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String res = "277923185514690367474770683";
+ int resScale = 0;
+ String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal)
+ */
+ public void testDivideAndRemainder2() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ String res = "2779231855146903674747706830969461168692256919247547952" +
+ "2608549363170374005512836303475980101168105698072946555" +
+ "6862849";
+ int resScale = 0;
+ String rem = "3.4935796954060524114470681810486417234751682675102093970E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal, MathContext)
+ */
+ public void testDivideAndRemainderMathContextUP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 70;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "277923185514690367474770683";
+ int resScale = 0;
+ String rem = "1.3032693871288309587558885943391070087960319452465789990E-15";
+ int remScale = 70;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * divideAndRemainder(BigDecimal, MathContext)
+ */
+ public void testDivideAndRemainderMathContextDOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 20;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "0E-25";
+ int resScale = 25;
+ String rem = "3736186567876.876578956958765675671119238118911893939591735";
+ int remScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result[] = aNumber.divideAndRemainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result[0].toString());
+ assertEquals("incorrect quotient scale", resScale, result[0].scale());
+ assertEquals("incorrect remainder value", rem, result[1].toString());
+ assertEquals("incorrect remainder scale", remScale, result[1].scale());
+ }
+
+ /**
+ * remainder(BigDecimal)
+ */
+ public void testRemainder1() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ int resScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal)
+ */
+ public void testRemainder2() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ String res = "1149310942946292909508821656680979993738625937.2065885780";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal, MathContext)
+ */
+ public void testRemainderMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ int resScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * remainder(BigDecimal, MathContext)
+ */
+ public void testRemainderMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ String b = "134432345432345748766876876723342238476237823787879183470";
+ int bScale = 10;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1149310942946292909508821656680979993738625937.2065885780";
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal result = aNumber.remainder(bNumber, mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext)
+ */
+ public void testRoundMathContextHALF_DOWN() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ int precision = 75;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3.736186567876876578956958765675671119238118911893939591735E+102";
+ int resScale = -45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext)
+ */
+ public void testRoundMathContextHALF_UP() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.88";
+ int resScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", resScale, result.scale());
+ }
+
+ /**
+ * round(BigDecimal, MathContext) when precision = 0
+ */
+ public void testRoundMathContextPrecision0() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ int precision = 0;
+ RoundingMode rm = RoundingMode.HALF_UP;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "3736186567876.876578956958765675671119238118911893939591735";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.round(mc);
+ assertEquals("incorrect quotient value", res, result.toString());
+ assertEquals("incorrect quotient scale", aScale, result.scale());
+ }
+
+
+ /**
+ * ulp() of a positive BigDecimal
+ */
+ public void testUlpPos() {
+ String a = "3736186567876876578956958765675671119238118911893939591735";
+ int aScale = -45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "1E+45";
+ int resScale = -45;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * ulp() of a negative BigDecimal
+ */
+ public void testUlpNeg() {
+ String a = "-3736186567876876578956958765675671119238118911893939591735";
+ int aScale = 45;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "1E-45";
+ int resScale = 45;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * ulp() of a negative BigDecimal
+ */
+ public void testUlpZero() {
+ String a = "0";
+ int aScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.ulp();
+ String res = "0.01";
+ int resScale = 2;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java
new file mode 100644
index 0000000..df756a1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalCompareTest.java
@@ -0,0 +1,512 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class: java.math.BigDecimal
+ * Methods: abs, compareTo, equals, hashCode,
+ * max, min, negate, signum
+ */
+public class BigDecimalCompareTest extends TestCase {
+ /**
+ * Abs() of a negative BigDecimal
+ */
+ public void testAbsNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123809648392384754573567356745735635678902957849027687.87678287";
+ assertEquals("incorrect value", result, aNumber.abs().toString());
+ }
+
+ /**
+ * Abs() of a positive BigDecimal
+ */
+ public void testAbsPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123809648392384754573567356745735635678902957849027687.87678287";
+ assertEquals("incorrect value", result, aNumber.abs().toString());
+ }
+
+ /**
+ * Abs(MathContext) of a negative BigDecimal
+ */
+ public void testAbsMathContextNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int precision = 15;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mc = new MathContext(precision, rm);
+ String result = "1.23809648392385E+53";
+ int resScale = -39;
+ BigDecimal res = aNumber.abs(mc);
+ assertEquals("incorrect value", result, res.toString());
+ assertEquals("incorrect scale", resScale, res.scale());
+ }
+
+ /**
+ * Abs(MathContext) of a positive BigDecimal
+ */
+ public void testAbsMathContextPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int precision = 41;
+ RoundingMode rm = RoundingMode.HALF_EVEN;
+ MathContext mc = new MathContext(precision, rm);
+ String result = "1.2380964839238475457356735674573563567890E+53";
+ int resScale = -13;
+ BigDecimal res = aNumber.abs(mc);
+ assertEquals("incorrect value", result, res.toString());
+ assertEquals("incorrect scale", resScale, res.scale());
+ }
+
+ /**
+ * Compare to a number of an equal scale
+ */
+ public void testCompareEqualScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an equal scale
+ */
+ public void testCompareEqualScale2() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563923487289357829759278282992758247567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an greater scale
+ */
+ public void testCompareGreaterScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 28;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an greater scale
+ */
+ public void testCompareGreaterScale2() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 48;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 2;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an less scale
+ */
+ public void testCompareLessScale1() {
+ String a = "12380964839238475457356735674573563567890295784902768787678287";
+ int aScale = 18;
+ String b = "4573563567890295784902768787678287";
+ int bScale = 28;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = 1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Compare to a number of an less scale
+ */
+ public void testCompareLessScale2() {
+ String a = "12380964839238475457356735674573";
+ int aScale = 36;
+ String b = "45735635948573894578349572001798379183767890295784902768787678287";
+ int bScale = 48;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ int result = -1;
+ assertEquals("incorrect result", result, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals
+ */
+ public void testEqualsUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "7472334223847623782375469293018787918347987234564568";
+ int bScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals
+ */
+ public void testEqualsUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * Equals() for unequal BigDecimals
+ */
+ public void testEqualsUnequal3() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertFalse(aNumber.equals(b));
+ }
+
+ /**
+ * equals() for equal BigDecimals
+ */
+ public void testEqualsEqual() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertEquals(aNumber, bNumber);
+ }
+
+ /**
+ * equals() for equal BigDecimals
+ */
+ public void testEqualsNull() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertFalse(aNumber.equals(null));
+ }
+
+ /**
+ * hashCode() for equal BigDecimals
+ */
+ public void testHashCodeEqual() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = -24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertEquals("incorrect value", aNumber.hashCode(), bNumber.hashCode());
+ }
+
+ /**
+ * hashCode() for unequal BigDecimals
+ */
+ public void testHashCodeUnequal() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = -24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ assertTrue("incorrect value", aNumber.hashCode() != bNumber.hashCode());
+ }
+
+ /**
+ * max() for equal BigDecimals
+ */
+ public void testMaxEqual() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "8478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "8478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * max() for unequal BigDecimals
+ */
+ public void testMaxUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 24;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * max() for unequal BigDecimals
+ */
+ public void testMaxUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "94488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.max(bNumber));
+ }
+
+ /**
+ * min() for equal BigDecimals
+ */
+ public void testMinEqual() {
+ String a = "8478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "8478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "8478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * min() for unequal BigDecimals
+ */
+ public void testMinUnequal1() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 24;
+ String b = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * min() for unequal BigDecimals
+ */
+ public void testMinUnequal2() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String b = "94488478231212478987482988429808779810457634781384756794987";
+ int bScale = 41;
+ String c = "94488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = new BigDecimal(new BigInteger(b), bScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.min(bNumber));
+ }
+
+ /**
+ * plus() for a positive BigDecimal
+ */
+ public void testPlusPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.plus());
+ }
+
+ /**
+ * plus(MathContext) for a positive BigDecimal
+ */
+ public void testPlusMathContextPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ int precision = 37;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "929487820944884782312124789.8748298842";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.plus(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * plus() for a negative BigDecimal
+ */
+ public void testPlusNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.plus());
+ }
+
+ /**
+ * plus(MathContext) for a negative BigDecimal
+ */
+ public void testPlusMathContextNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 49;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "-9294878209448847823.121247898748298842980877981";
+ int cScale = 27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.plus(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * negate() for a positive BigDecimal
+ */
+ public void testNegatePositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.negate());
+ }
+
+ /**
+ * negate(MathContext) for a positive BigDecimal
+ */
+ public void testNegateMathContextPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ int precision = 37;
+ RoundingMode rm = RoundingMode.FLOOR;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "-929487820944884782312124789.8748298843";
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.negate(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * negate() for a negative BigDecimal
+ */
+ public void testNegateNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ String c = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int cScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal cNumber = new BigDecimal(new BigInteger(c), cScale);
+ assertEquals("incorrect value", cNumber, aNumber.negate());
+ }
+
+ /**
+ * negate(MathContext) for a negative BigDecimal
+ */
+ public void testNegateMathContextNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 49;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String c = "9294878209448847823.121247898748298842980877982";
+ int cScale = 27;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal res = aNumber.negate(mc);
+ assertEquals("incorrect value", c, res.toString());
+ assertEquals("incorrect scale", cScale, res.scale());
+ }
+
+ /**
+ * signum() for a positive BigDecimal
+ */
+ public void testSignumPositive() {
+ String a = "92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", 1, aNumber.signum());
+ }
+
+ /**
+ * signum() for a negative BigDecimal
+ */
+ public void testSignumNegative() {
+ String a = "-92948782094488478231212478987482988429808779810457634781384756794987";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", -1, aNumber.signum());
+ }
+
+ /**
+ * signum() for zero
+ */
+ public void testSignumZero() {
+ String a = "0";
+ int aScale = 41;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertEquals("incorrect value", 0, aNumber.signum());
+ }
+
+ /*
+ * Regression test for HARMONY-6406
+ */
+ public void testApproxPrecision() {
+ BigDecimal testInstance = BigDecimal.TEN.multiply(new BigDecimal("0.1"));
+ int result = testInstance.compareTo(new BigDecimal("1.00"));
+ assertEquals(0, result);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java
new file mode 100644
index 0000000..3838991
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConstructorsTest.java
@@ -0,0 +1,684 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+import junit.framework.TestCase;
+
+/**
+ * Class: java.math.BigDecimal
+ * Methods: constructors and fields
+ */
+public class BigDecimalConstructorsTest extends TestCase {
+ /**
+ * check ONE
+ */
+ public void testFieldONE() {
+ String oneS = "1";
+ double oneD = 1.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.ONE.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.ONE.doubleValue(), 0);
+ }
+
+ /**
+ * check TEN
+ */
+ public void testFieldTEN() {
+ String oneS = "10";
+ double oneD = 10.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.TEN.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.TEN.doubleValue(), 0);
+ }
+
+ /**
+ * check ZERO
+ */
+ public void testFieldZERO() {
+ String oneS = "0";
+ double oneD = 0.0;
+ assertEquals("incorrect string value", oneS, BigDecimal.ZERO.toString());
+ assertEquals("incorrect double value", oneD, BigDecimal.ZERO.doubleValue(), 0);
+ }
+
+ /**
+ * new BigDecimal(BigInteger value)
+ */
+ public void testConstrBI() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ BigDecimal aNumber = new BigDecimal(bA);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", 0, aNumber.scale());
+
+ try {
+ new BigDecimal((BigInteger) null);
+ fail("No NullPointerException");
+ } catch (NullPointerException e) {
+ //expected
+ }
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, int scale)
+ */
+ public void testConstrBIScale() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int aScale = 10;
+ BigDecimal aNumber = new BigDecimal(bA, aScale);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, MathContext)
+ */
+ public void testConstrBigIntegerMathContext() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1231212478987482988429808779810457634781384757";
+ int resScale = -6;
+ BigDecimal result = new BigDecimal(bA, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(BigInteger value, int scale, MathContext)
+ */
+ public void testConstrBigIntegerScaleMathContext() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ BigInteger bA = new BigInteger(a);
+ int aScale = 10;
+ int precision = 46;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "1231212478987482988429808779810457634781384757";
+ int resScale = 4;
+ BigDecimal result = new BigDecimal(bA, aScale, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(char[] value);
+ */
+ public void testConstrChar() {
+ char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+ BigDecimal result = new BigDecimal(value);
+ String res = "-1.23804738E-419";
+ int resScale = 427;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {});
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len);
+ */
+ public void testConstrCharIntInt() {
+ char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+ int offset = 3;
+ int len = 12;
+ BigDecimal result = new BigDecimal(value, offset, len);
+ String res = "3.804738E-40";
+ int resScale = 46;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {}, 0, 0);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc);
+ */
+ public void testConstrCharIntIntMathContext() {
+ char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+ int offset = 3;
+ int len = 12;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ BigDecimal result = new BigDecimal(value, offset, len, mc);
+ String res = "3.805E-40";
+ int resScale = 43;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {}, 0, 0, MathContext.DECIMAL32);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc);
+ */
+ public void testConstrCharIntIntMathContextException1() {
+ char value[] = {'-', '1', '2', '3', '8', '0', '.', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+ int offset = 3;
+ int len = 120;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ try {
+ new BigDecimal(value, offset, len, mc);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, int offset, int len, MathContext mc);
+ */
+ public void testConstrCharIntIntMathContextException2() {
+ char value[] = {'-', '1', '2', '3', '8', '0', ',', '4', '7', '3', '8', 'E', '-', '4', '2', '3'};
+ int offset = 3;
+ int len = 120;
+ int precision = 4;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ try {
+ new BigDecimal(value, offset, len, mc);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(char[] value, MathContext mc);
+ */
+ public void testConstrCharMathContext() {
+ try {
+ // Regression for HARMONY-783
+ new BigDecimal(new char[] {}, MathContext.DECIMAL32);
+ fail("NumberFormatException has not been thrown");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(double value) when value is NaN
+ */
+ public void testConstrDoubleNaN() {
+ double a = Double.NaN;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(double value) when value is positive infinity
+ */
+ public void testConstrDoublePosInfinity() {
+ double a = Double.POSITIVE_INFINITY;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(double value) when value is positive infinity
+ */
+ public void testConstrDoubleNegInfinity() {
+ double a = Double.NEGATIVE_INFINITY;
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(double value)
+ */
+ public void testConstrDouble() {
+ double a = 732546982374982347892379283571094797.287346782359284756;
+ int aScale = 0;
+ BigInteger bA = new BigInteger("732546982374982285073458350476230656");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(double, MathContext)
+ */
+ public void testConstrDoubleMathContext() {
+ double a = 732546982374982347892379283571094797.287346782359284756;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "732546982374982285074";
+ int resScale = -15;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(0.1)
+ */
+ public void testConstrDouble01() {
+ double a = 1.E-1;
+ int aScale = 55;
+ BigInteger bA = new BigInteger("1000000000000000055511151231257827021181583404541015625");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(0.555)
+ */
+ public void testConstrDouble02() {
+ double a = 0.555;
+ int aScale = 53;
+ BigInteger bA = new BigInteger("55500000000000004884981308350688777863979339599609375");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(-0.1)
+ */
+ public void testConstrDoubleMinus01() {
+ double a = -1.E-1;
+ int aScale = 55;
+ BigInteger bA = new BigInteger("-1000000000000000055511151231257827021181583404541015625");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(int value)
+ */
+ public void testConstrInt() {
+ int a = 732546982;
+ String res = "732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(int, MathContext)
+ */
+ public void testConstrIntMathContext() {
+ int a = 732546982;
+ int precision = 21;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(long value)
+ */
+ public void testConstrLong() {
+ long a = 4576578677732546982L;
+ String res = "4576578677732546982";
+ int resScale = 0;
+ BigDecimal result = new BigDecimal(a);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(long, MathContext)
+ */
+ public void testConstrLongMathContext() {
+ long a = 4576578677732546982L;
+ int precision = 5;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "45766";
+ int resScale = -14;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * new BigDecimal(double value) when value is denormalized
+ */
+ public void testConstrDoubleDenormalized() {
+ double a = 2.274341322658976E-309;
+ int aScale = 1073;
+ BigInteger bA = new BigInteger("227434132265897633950269241702666687639731047124115603942986140264569528085692462493371029187342478828091760934014851133733918639492582043963243759464684978401240614084312038547315281016804838374623558434472007664427140169018817050565150914041833284370702366055678057809362286455237716100382057360123091641959140448783514464639706721250400288267372238950016114583259228262046633530468551311769574111763316146065958042194569102063373243372766692713192728878701004405568459288708477607744497502929764155046100964958011009313090462293046650352146796805866786767887226278836423536035611825593567576424943331337401071583562754098901412372708947790843318760718495117047155597276492717187936854356663665005157041552436478744491526494952982062613955349661409854888916015625");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value)
+ * when value is not a valid representation of BigDecimal.
+ */
+ public void testConstrStringException() {
+ String a = "-238768.787678287a+10";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {}
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is empty.
+ */
+ public void testConstrStringExceptionEmptyExponent1() {
+ String a = "-238768.787678287e";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is empty.
+ */
+ public void testConstrStringExceptionEmptyExponent2() {
+ String a = "-238768.787678287e-";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is greater than
+ * Integer.MAX_VALUE.
+ */
+ public void testConstrStringExceptionExponentGreaterIntegerMax() {
+ String a = "-238768.787678287e214748364767876";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value) when exponent is less than
+ * Integer.MIN_VALUE.
+ */
+ public void testConstrStringExceptionExponentLessIntegerMin() {
+ String a = "-238768.787678287e-214748364767876";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value)
+ * when exponent is Integer.MAX_VALUE.
+ */
+ public void testConstrStringExponentIntegerMax() {
+ String a = "-238768.787678287e2147483647";
+ int aScale = -2147483638;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value)
+ * when exponent is Integer.MIN_VALUE.
+ */
+ public void testConstrStringExponentIntegerMin() {
+ String a = ".238768e-2147483648";
+ try {
+ new BigDecimal(a);
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent
+ */
+ public void testConstrStringWithoutExpPos1() {
+ String a = "732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger("732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent
+ */
+ public void testConstrStringWithoutExpPos2() {
+ String a = "+732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger("732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent
+ */
+ public void testConstrStringWithoutExpNeg() {
+ String a = "-732546982374982347892379283571094797.287346782359284756";
+ int aScale = 18;
+ BigInteger bA = new BigInteger("-732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value does not contain exponent
+ * and decimal point
+ */
+ public void testConstrStringWithoutExpWithoutPoint() {
+ String a = "-732546982374982347892379283571094797287346782359284756";
+ int aScale = 0;
+ BigInteger bA = new BigInteger("-732546982374982347892379283571094797287346782359284756");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent
+ * and does not contain decimal point
+ */
+ public void testConstrStringWithExponentWithoutPoint1() {
+ String a = "-238768787678287e214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent
+ * and does not contain decimal point
+ */
+ public void testConstrStringWithExponentWithoutPoint2() {
+ String a = "-238768787678287e-214";
+ int aScale = 214;
+ BigInteger bA = new BigInteger("-238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent
+ * and does not contain decimal point
+ */
+ public void testConstrStringWithExponentWithoutPoint3() {
+ String a = "238768787678287e-214";
+ int aScale = 214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent
+ * and does not contain decimal point
+ */
+ public void testConstrStringWithExponentWithoutPoint4() {
+ String a = "238768787678287e+214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value); value contains exponent
+ * and does not contain decimal point
+ */
+ public void testConstrStringWithExponentWithoutPoint5() {
+ String a = "238768787678287E214";
+ int aScale = -214;
+ BigInteger bA = new BigInteger("238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value);
+ * value contains both exponent and decimal point
+ */
+ public void testConstrStringWithExponentWithPoint1() {
+ String a = "23985439837984782435652424523876878.7678287e+214";
+ int aScale = -207;
+ BigInteger bA = new BigInteger("239854398379847824356524245238768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value);
+ * value contains both exponent and decimal point
+ */
+ public void testConstrStringWithExponentWithPoint2() {
+ String a = "238096483923847545735673567457356356789029578490276878.7678287e-214";
+ int aScale = 221;
+ BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value);
+ * value contains both exponent and decimal point
+ */
+ public void testConstrStringWithExponentWithPoint3() {
+ String a = "2380964839238475457356735674573563567890.295784902768787678287E+21";
+ int aScale = 0;
+ BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value);
+ * value contains both exponent and decimal point
+ */
+ public void testConstrStringWithExponentWithPoint4() {
+ String a = "23809648392384754573567356745735635678.90295784902768787678287E+21";
+ int aScale = 2;
+ BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value);
+ * value contains both exponent and decimal point
+ */
+ public void testConstrStringWithExponentWithPoint5() {
+ String a = "238096483923847545735673567457356356789029.5784902768787678287E+21";
+ int aScale = -2;
+ BigInteger bA = new BigInteger("2380964839238475457356735674573563567890295784902768787678287");
+ BigDecimal aNumber = new BigDecimal(a);
+ assertEquals("incorrect value", bA, aNumber.unscaledValue());
+ assertEquals("incorrect scale", aScale, aNumber.scale());
+ }
+
+ /**
+ * new BigDecimal(String value, MathContext)
+ */
+ public void testConstrStringMathContext() {
+ String a = "-238768787678287e214";
+ int precision = 5;
+ RoundingMode rm = RoundingMode.CEILING;
+ MathContext mc = new MathContext(precision, rm);
+ String res = "-23876";
+ int resScale = -224;
+ BigDecimal result = new BigDecimal(a, mc);
+ assertEquals("incorrect value", res, result.unscaledValue().toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java
new file mode 100644
index 0000000..67fd8b4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalConvertTest.java
@@ -0,0 +1,569 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigDecimal
+ * Methods: doubleValue, floatValue, intValue, longValue,
+ * valueOf, toString, toBigInteger
+ */
+public class BigDecimalConvertTest extends TestCase {
+ /**
+ * Double value of a negative BigDecimal
+ */
+ public void testDoubleValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = -1.2380964839238476E53;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a positive BigDecimal
+ */
+ public void testDoubleValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = 1.2380964839238476E53;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a large positive BigDecimal
+ */
+ public void testDoubleValuePosInfinity() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+400";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = Double.POSITIVE_INFINITY;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a large negative BigDecimal
+ */
+ public void testDoubleValueNegInfinity() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+400";
+ BigDecimal aNumber = new BigDecimal(a);
+ double result = Double.NEGATIVE_INFINITY;
+ assertEquals("incorrect value", result, aNumber.doubleValue(), 0);
+ }
+
+ /**
+ * Double value of a small negative BigDecimal
+ */
+ public void testDoubleValueMinusZero() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+ BigDecimal aNumber = new BigDecimal(a);
+ long minusZero = -9223372036854775808L;
+ double result = aNumber.doubleValue();
+ assertTrue("incorrect value", Double.doubleToLongBits(result) == minusZero);
+ }
+
+ /**
+ * Double value of a small positive BigDecimal
+ */
+ public void testDoubleValuePlusZero() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+ BigDecimal aNumber = new BigDecimal(a);
+ long zero = 0;
+ double result = aNumber.doubleValue();
+ assertTrue("incorrect value", Double.doubleToLongBits(result) == zero);
+ }
+
+ /**
+ * Float value of a negative BigDecimal
+ */
+ public void testFloatValueNeg() {
+ String a = "-1238096483923847.6356789029578E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = -1.2380965E36F;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Float value of a positive BigDecimal
+ */
+ public void testFloatValuePos() {
+ String a = "1238096483923847.6356789029578E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = 1.2380965E36F;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Float value of a large positive BigDecimal
+ */
+ public void testFloatValuePosInfinity() {
+ String a = "123809648373567356745735.6356789787678287E+200";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = Float.POSITIVE_INFINITY;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Float value of a large negative BigDecimal
+ */
+ public void testFloatValueNegInfinity() {
+ String a = "-123809648392384755735.63567887678287E+200";
+ BigDecimal aNumber = new BigDecimal(a);
+ float result = Float.NEGATIVE_INFINITY;
+ assertTrue("incorrect value", aNumber.floatValue() == result);
+ }
+
+ /**
+ * Float value of a small negative BigDecimal
+ */
+ public void testFloatValueMinusZero() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-400";
+ BigDecimal aNumber = new BigDecimal(a);
+ int minusZero = -2147483648;
+ float result = aNumber.floatValue();
+ assertTrue("incorrect value", Float.floatToIntBits(result) == minusZero);
+ }
+
+ /**
+ * Float value of a small positive BigDecimal
+ */
+ public void testFloatValuePlusZero() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-400";
+ BigDecimal aNumber = new BigDecimal(a);
+ int zero = 0;
+ float result = aNumber.floatValue();
+ assertTrue("incorrect value", Float.floatToIntBits(result) == zero);
+ }
+
+ /**
+ * Integer value of a negative BigDecimal
+ */
+ public void testIntValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int result = 218520473;
+ assertTrue("incorrect value", aNumber.intValue() == result);
+ }
+
+ /**
+ * Integer value of a positive BigDecimal
+ */
+ public void testIntValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ int result = -218520473;
+ assertTrue("incorrect value", aNumber.intValue() == result);
+ }
+
+ /**
+ * Long value of a negative BigDecimal
+ */
+ public void testLongValueNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ long result = -1246043477766677607L;
+ assertTrue("incorrect value", aNumber.longValue() == result);
+ }
+
+ /**
+ * Long value of a positive BigDecimal
+ */
+ public void testLongValuePos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigDecimal aNumber = new BigDecimal(a);
+ long result = 1246043477766677607L;
+ assertTrue("incorrect value", aNumber.longValue() == result);
+ }
+
+ /**
+ * scaleByPowerOfTen(int n)
+ */
+ public void testScaleByPowerOfTen1() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.scaleByPowerOfTen(10);
+ String res = "1231212478987482988429808779810457634781384756794.987";
+ int resScale = 3;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * scaleByPowerOfTen(int n)
+ */
+ public void testScaleByPowerOfTen2() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -13;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.scaleByPowerOfTen(10);
+ String res = "1.231212478987482988429808779810457634781384756794987E+74";
+ int resScale = -23;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger
+ */
+ public void testToBigIntegerPos1() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849027687");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger
+ */
+ public void testToBigIntegerPos2() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+15";
+ BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a positive BigDecimal to BigInteger
+ */
+ public void testToBigIntegerPos3() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigInteger bNumber = new BigInteger("123809648392384754573567356745735635678902957849027687876782870000000000000000");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger
+ */
+ public void testToBigIntegerNeg1() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+21";
+ BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849027687");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger
+ */
+ public void testToBigIntegerNeg2() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+15";
+ BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a negative BigDecimal to BigInteger
+ */
+ public void testToBigIntegerNeg3() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigInteger bNumber = new BigInteger("-123809648392384754573567356745735635678902957849027687876782870000000000000000");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * Convert a small BigDecimal to BigInteger
+ */
+ public void testToBigIntegerZero() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-500";
+ BigInteger bNumber = new BigInteger("0");
+ BigDecimal aNumber = new BigDecimal(a);
+ BigInteger result = aNumber.toBigInteger();
+ assertTrue("incorrect value", result.equals(bNumber));
+ }
+
+ /**
+ * toBigIntegerExact()
+ */
+ public void testToBigIntegerExact1() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E+45";
+ BigDecimal aNumber = new BigDecimal(a);
+ String res = "-123809648392384754573567356745735635678902957849027687876782870000000000000000";
+ BigInteger result = aNumber.toBigIntegerExact();
+ assertEquals("incorrect value", res, result.toString());
+ }
+
+ /**
+ * toBigIntegerExact()
+ */
+ public void testToBigIntegerExactException() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-10";
+ BigDecimal aNumber = new BigDecimal(a);
+ try {
+ aNumber.toBigIntegerExact();
+ fail("java.lang.ArithmeticException has not been thrown");
+ } catch (java.lang.ArithmeticException e) {
+ return;
+ }
+ }
+
+ /**
+ * Convert a positive BigDecimal to an engineering string representation
+ */
+ public void testToEngineeringStringPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-501";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "123.80964839238475457356735674573563567890295784902768787678287E-471";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation
+ */
+ public void testToEngineeringStringNeg() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-501";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-123.80964839238475457356735674573563567890295784902768787678287E-471";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation
+ */
+ public void testToEngineeringStringZeroPosExponent() {
+ String a = "0.0E+16";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0E+15";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal to an engineering string representation
+ */
+ public void testToEngineeringStringZeroNegExponent() {
+ String a = "0.0E-16";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0.00E-15";
+ assertEquals("incorrect value", result, aNumber.toEngineeringString());
+ }
+
+ /**
+ * Convert a negative BigDecimal with a negative exponent to a plain string
+ * representation; scale == 0.
+ */
+ public void testToPlainStringNegNegExp() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E-100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal with a positive exponent
+ * to a plain string representation;
+ * scale == 0.
+ */
+ public void testToPlainStringNegPosExp() {
+ String a = "-123809648392384754573567356745735.63567890295784902768787678287E100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a positive BigDecimal with a negative exponent
+ * to a plain string representation;
+ * scale == 0.
+ */
+ public void testToPlainStringPosNegExp() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "0.000000000000000000000000000000000000000000000000000000000000000000012380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal with a negative exponent
+ * to a plain string representation;
+ * scale == 0.
+ */
+ public void testToPlainStringPosPosExp() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E+100";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "1238096483923847545735673567457356356789029578490276878767828700000000000000000000000000000000000000000000000000000000000000000000000";
+ assertTrue("incorrect value", aNumber.toPlainString().equals(result));
+ }
+
+ /**
+ * Convert a BigDecimal to a string representation;
+ * scale == 0.
+ */
+ public void testToStringZeroScale() {
+ String a = "-123809648392384754573567356745735635678902957849027687876782870";
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+ String result = "-123809648392384754573567356745735635678902957849027687876782870";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Convert a positive BigDecimal to a string representation
+ */
+ public void testToStringPos() {
+ String a = "123809648392384754573567356745735.63567890295784902768787678287E-500";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "1.2380964839238475457356735674573563567890295784902768787678287E-468";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Convert a negative BigDecimal to a string representation
+ */
+ public void testToStringNeg() {
+ String a = "-123.4564563673567380964839238475457356735674573563567890295784902768787678287E-5";
+ BigDecimal aNumber = new BigDecimal(a);
+ String result = "-0.001234564563673567380964839238475457356735674573563567890295784902768787678287";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a positive long value; scale == 0
+ */
+ public void testValueOfPosZeroScale() {
+ long a = 98374823947823578L;
+ BigDecimal aNumber = BigDecimal.valueOf(a);
+ String result = "98374823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is 0
+ */
+ public void testValueOfNegZeroScale() {
+ long a = -98374823947823578L;
+ BigDecimal aNumber = BigDecimal.valueOf(a);
+ String result = "-98374823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is positive
+ */
+ public void testValueOfNegScalePos() {
+ long a = -98374823947823578L;
+ int scale = 12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "-98374.823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is negative
+ */
+ public void testValueOfNegScaleNeg() {
+ long a = -98374823947823578L;
+ int scale = -12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "-9.8374823947823578E+28";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is positive
+ */
+ public void testValueOfPosScalePos() {
+ long a = 98374823947823578L;
+ int scale = 12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "98374.823947823578";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative long value; scale is negative
+ */
+ public void testValueOfPosScaleNeg() {
+ long a = 98374823947823578L;
+ int scale = -12;
+ BigDecimal aNumber = BigDecimal.valueOf(a, scale);
+ String result = "9.8374823947823578E+28";
+ assertTrue("incorrect value", aNumber.toString().equals(result));
+ }
+
+ /**
+ * Create a BigDecimal from a negative double value
+ */
+ public void testValueOfDoubleNeg() {
+ double a = -65678765876567576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "-65678765876567576";
+ int resScale = 0;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value
+ */
+ public void testValueOfDoublePos1() {
+ double a = 65678765876567576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "65678765876567576";
+ int resScale = 0;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value
+ */
+ public void testValueOfDoublePos2() {
+ double a = 12321237576.98788767;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "12321237576.987888";
+ int resScale = 6;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Create a BigDecimal from a positive double value
+ */
+ public void testValueOfDoublePos3() {
+ double a = 12321237576.9878838;
+ BigDecimal result = BigDecimal.valueOf(a);
+ String res = "12321237576.987885";
+ int resScale = 6;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * valueOf(Double.NaN)
+ */
+ public void testValueOfDoubleNaN() {
+ double a = Double.NaN;
+ try {
+ BigDecimal.valueOf(a);
+ fail("NumberFormatException has not been thrown for Double.NaN");
+ } catch (NumberFormatException e) {
+ return;
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java
new file mode 100644
index 0000000..6c74dee
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigDecimalScaleOperationsTest.java
@@ -0,0 +1,348 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.*;
+
+/**
+ * Class: java.math.BigDecimal
+ * Methods: movePointLeft, movePointRight, scale, setScale, unscaledValue *
+ */
+public class BigDecimalScaleOperationsTest extends TestCase {
+ /**
+ * Check the default scale
+ */
+ public void testScaleDefault() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a));
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check a negative scale
+ */
+ public void testScaleNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = -10;
+ int cScale = -10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check a positive scale
+ */
+ public void testScalePos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 10;
+ int cScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check the zero scale
+ */
+ public void testScaleZero() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 0;
+ int cScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ assertTrue("incorrect scale", aNumber.scale() == cScale);
+ }
+
+ /**
+ * Check the unscaled value
+ */
+ public void testUnscaledValue() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 100;
+ BigInteger bNumber = new BigInteger(a);
+ BigDecimal aNumber = new BigDecimal(bNumber, aScale);
+ assertTrue("incorrect unscaled value", aNumber.unscaledValue().equals(bNumber));
+ }
+
+ /**
+ * Set a greater new scale
+ */
+ public void testSetScaleGreater() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 18;
+ int newScale = 28;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+ }
+
+ /**
+ * Set a less new scale; this.scale == 8; newScale == 5.
+ */
+ public void testSetScaleLess() {
+ String a = "2.345726458768760000E+10";
+ int newScale = 5;
+ BigDecimal aNumber = new BigDecimal(a);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertEquals("incorrect value", 0, bNumber.compareTo(aNumber));
+ }
+
+ /**
+ * Verify an exception when setting a new scale
+ */
+ public void testSetScaleException() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ try {
+ aNumber.setScale(newScale);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ assertEquals("Improper exception message", "Rounding necessary", e.getMessage());
+ }
+ }
+
+ /**
+ * Set the same new scale
+ */
+ public void testSetScaleSame() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 18;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.equals(aNumber));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundUp() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478139";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_UP);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundDown() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_DOWN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundCeiling() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478139";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_CEILING);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundFloor() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_FLOOR);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfUp() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_UP);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfDown() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_DOWN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Set a new scale
+ */
+ public void testSetScaleRoundHalfEven() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.setScale(newScale, BigDecimal.ROUND_HALF_EVEN);
+ assertTrue("incorrect scale", bNumber.scale() == newScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * SetScale(int, RoundingMode)
+ */
+ public void testSetScaleIntRoundingMode() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int newScale = 18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal result = aNumber.setScale(newScale, RoundingMode.HALF_EVEN);
+ String res = "123121247898748298842980.877981045763478138";
+ int resScale = 18;
+ assertEquals("incorrect value", res, result.toString());
+ assertEquals("incorrect scale", resScale, result.scale());
+ }
+
+ /**
+ * Move the decimal point to the left; the shift value is positive
+ */
+ public void testMovePointLeftPos() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = 18;
+ int resScale = 46;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointLeft(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the left; the shift value is positive
+ */
+ public void testMovePointLeftNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = -18;
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointLeft(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightPosGreater() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = 18;
+ int resScale = 10;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightPosLess() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ String b = "123121247898748298842980877981045763478138475679498700";
+ int aScale = 28;
+ int shift = 30;
+ int resScale = 0;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(b));
+ }
+
+ /**
+ * Move the decimal point to the right; the shift value is positive
+ */
+ public void testMovePointRightNeg() {
+ String a = "1231212478987482988429808779810457634781384756794987";
+ int aScale = 28;
+ int shift = -18;
+ int resScale = 46;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ BigDecimal bNumber = aNumber.movePointRight(shift);
+ assertTrue("incorrect scale", bNumber.scale() == resScale);
+ assertTrue("incorrect value", bNumber.unscaledValue().toString().equals(a));
+ }
+
+ /**
+ * Move the decimal point to the right when the scale overflows
+ */
+ public void testMovePointRightException() {
+ String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+ int aScale = Integer.MAX_VALUE; //2147483647
+ int shift = -18;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ try {
+ aNumber.movePointRight(shift);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * precision()
+ */
+ public void testPrecision() {
+ String a = "12312124789874829887348723648726347429808779810457634781384756794987";
+ int aScale = 14;
+ BigDecimal aNumber = new BigDecimal(new BigInteger(a), aScale);
+ int prec = aNumber.precision();
+ assertEquals(68, prec);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java
new file mode 100644
index 0000000..913eb8a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAddTest.java
@@ -0,0 +1,495 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: add
+ */
+public class BigIntegerAddTest extends TestCase {
+ /**
+ * Add two positive numbers of the same length
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of the same length
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length.
+ * The first one is positive and the second is negative.
+ * The first one is greater in absolute value.
+ */
+ public void testCase3() {
+ byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length.
+ * The first one is negative and the second is positive.
+ * The first one is greater in absolute value.
+ */
+ public void testCase4() {
+ byte aBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length.
+ * The first is positive and the second is negative.
+ * The first is less in absolute value.
+ */
+ public void testCase5() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte rBytes[] = {-3, -3, -3, -3, -3, -3, -2};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of the same length.
+ * The first one is negative and the second is positive.
+ * The first one is less in absolute value.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {3, 4, 5, 6, 7, 8, 9};
+ byte rBytes[] = {2, 2, 2, 2, 2, 2, 2};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two positive numbers of different length.
+ * The first is longer.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two positive numbers of different length.
+ * The second is longer.
+ */
+ public void testCase8() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aBytes);
+ BigInteger bNumber = new BigInteger(bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of different length.
+ * The first is longer.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two negative numbers of different length.
+ * The second is longer.
+ */
+ public void testCase10() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign.
+ * The first is positive.
+ * The first is longer.
+ */
+ public void testCase11() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign.
+ * The first is positive.
+ * The second is longer.
+ */
+ public void testCase12() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign.
+ * The first is negative.
+ * The first is longer.
+ */
+ public void testCase13() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Add two numbers of different length and sign.
+ * The first is negative.
+ * The second is longer.
+ */
+ public void testCase14() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two equal numbers of different signs
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {0};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add zero to a number
+ */
+ public void testCase16() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add a number to zero
+ */
+ public void testCase17() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add zero to zero
+ */
+ public void testCase18() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ byte rBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add ZERO to a number
+ */
+ public void testCase19() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add a number to zero
+ */
+ public void testCase20() {
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int bSign = 1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add ZERO to ZERO
+ */
+ public void testCase21() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Add ONE to ONE
+ */
+ public void testCase22() {
+ byte rBytes[] = {2};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Add two numbers so that carry is 1
+ */
+ public void testCase23() {
+ byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -1, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.add(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java
new file mode 100644
index 0000000..d057bfa
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerAndTest.java
@@ -0,0 +1,432 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: and
+ */
+public class BigIntegerAndTest extends TestCase {
+ /**
+ * And for zero and a positive number
+ */
+ public void testZeroPos() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and a negative number
+ */
+ public void testZeroNeg() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for a positive number and zero
+ */
+ public void testPosZero() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for a negative number and zero
+ */
+ public void testNegPos() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = -1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and zero
+ */
+ public void testZeroZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for zero and one
+ */
+ public void testZeroOne() {
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.and(bNumber);
+ assertTrue(result.equals(BigInteger.ZERO));
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * And for one and one
+ */
+ public void testOneOne() {
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.and(bNumber);
+ assertTrue(result.equals(BigInteger.ONE));
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 56, 100, 4, 4, 17, 37, 16, 1, 64, 1, 10, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -76, 88, 44, 1, 2, 17, 35, 16, 9, 2, 5, 6, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 1, 2, 3, 3, 0, 65, -96, -48, -124, -60, 12, -40, -31, 97};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * And for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {0, -6, -80, 72, 8, 75, 2, -79, 34, 16, -119};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, 125, -60, -104, 1, 10, 6, 2, 32, 56, 2, 4, 4, 21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a negative and a positive numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * And for a positive and a negative numbers; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Test for a special case
+ */
+ public void testSpecialCase1() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ byte bBytes[] = {5, -4, -3, -2};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Test for a special case
+ */
+ public void testSpecialCase2() {
+ byte aBytes[] = {-51};
+ byte bBytes[] = {-52, -51, -50, -49, -48};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0, -52, -51, -50, -49, 16};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.and(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java
new file mode 100644
index 0000000..a65c77e
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerCompareTest.java
@@ -0,0 +1,533 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: abs, compareTo, equals, max, min, negate, signum
+ */
+public class BigIntegerCompareTest extends TestCase {
+ /**
+ * abs() for a positive number
+ */
+ public void testAbsPositive() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.abs();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * abs() for a negative number
+ */
+ public void testAbsNegative() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.abs();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two positive numbers.
+ * The first is greater.
+ */
+ public void testCompareToPosPos1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two positive numbers.
+ * The first is less.
+ */
+ public void testCompareToPosPos2() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two equal positive numbers.
+ */
+ public void testCompareToEqualPos() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two negative numbers.
+ * The first is greater in absolute value.
+ */
+ public void testCompareToNegNeg1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two negative numbers.
+ * The first is less in absolute value.
+ */
+ public void testCompareNegNeg2() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two equal negative numbers.
+ */
+ public void testCompareToEqualNeg() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two numbers of different signs.
+ * The first is positive.
+ */
+ public void testCompareToDiffSigns1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare two numbers of different signs.
+ * The first is negative.
+ */
+ public void testCompareToDiffSigns2() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare a positive number to ZERO.
+ */
+ public void testCompareToPosZero() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare ZERO to a positive number.
+ */
+ public void testCompareToZeroPos() {
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int bSign = 1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare a negative number to ZERO.
+ */
+ public void testCompareToNegZero() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(-1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare ZERO to a negative number.
+ */
+ public void testCompareToZeroNeg() {
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int bSign = -1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ assertEquals(1, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * compareTo(BigInteger a).
+ * Compare ZERO to ZERO.
+ */
+ public void testCompareToZeroZero() {
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ assertEquals(0, aNumber.compareTo(bNumber));
+ }
+
+ /**
+ * equals(Object obj).
+ * obj is not a BigInteger
+ */
+ public void testEqualsObject() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object obj = new Object();
+ assertFalse(aNumber.equals(obj));
+ }
+
+ /**
+ * equals(null).
+ */
+ public void testEqualsNull() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertFalse(aNumber.equals(null));
+ }
+
+ /**
+ * equals(Object obj).
+ * obj is a BigInteger.
+ * numbers are equal.
+ */
+ public void testEqualsBigIntegerTrue() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object bNumber = new BigInteger(bSign, bBytes);
+ assertTrue(aNumber.equals(bNumber));
+ }
+
+ /**
+ * equals(Object obj).
+ * obj is a BigInteger.
+ * numbers are not equal.
+ */
+ public void testEqualsBigIntegerFalse() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ Object bNumber = new BigInteger(bSign, bBytes);
+ assertFalse(aNumber.equals(bNumber));
+ }
+
+ /**
+ * max(BigInteger val).
+ * the first is greater.
+ */
+ public void testMaxGreater() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * max(BigInteger val).
+ * the first is less.
+ */
+ public void testMaxLess() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * max(BigInteger val).
+ * numbers are equal.
+ */
+ public void testMaxEqual() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * max(BigInteger val).
+ * max of negative and ZERO.
+ */
+ public void testMaxNegZero() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.max(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 0);
+ }
+
+ /**
+ * min(BigInteger val).
+ * the first is greater.
+ */
+ public void testMinGreater() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * min(BigInteger val).
+ * the first is less.
+ */
+ public void testMinLess() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * min(BigInteger val).
+ * numbers are equal.
+ */
+ public void testMinEqual() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ byte bBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * max(BigInteger val).
+ * min of positive and ZERO.
+ */
+ public void testMinPosZero() {
+ byte aBytes[] = {45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.min(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 0);
+ }
+
+ /**
+ * negate() a positive number.
+ */
+ public void testNegatePositive() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, -4, -91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == -1);
+ }
+
+ /**
+ * negate() a negative number.
+ */
+ public void testNegateNegative() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertTrue("incorrect sign", result.signum() == 1);
+ }
+
+ /**
+ * negate() ZERO.
+ */
+ public void testNegateZero() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.negate();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * signum() of a positive number.
+ */
+ public void testSignumPositive() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * signum() of a negative number.
+ */
+ public void testSignumNegative() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * signum() of ZERO.
+ */
+ public void testSignumZero() {
+ BigInteger aNumber = BigInteger.ZERO;
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java
new file mode 100644
index 0000000..1e0e4a1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConstructorsTest.java
@@ -0,0 +1,786 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+import java.util.Random;
+
+/**
+ * Class: java.math.BigInteger
+ * Constructors: BigInteger(byte[] a), BigInteger(int sign, byte[] a),
+ * BigInteger(String val, int radix)
+ */
+public class BigIntegerConstructorsTest extends TestCase {
+ /**
+ * Create a number from an array of bytes.
+ * Verify an exception thrown if an array is zero bytes long
+ */
+ public void testConstructorBytesException() {
+ byte aBytes[] = {};
+ try {
+ new BigInteger(aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a positive number from an array of bytes.
+ * The number fits in an array of integers.
+ */
+ public void testConstructorBytesPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes.
+ * The number fits in an integer.
+ */
+ public void testConstructorBytesPositive2() {
+ byte aBytes[] = {12, 56, 100};
+ byte rBytes[] = {12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes.
+ * The number of bytes is 4.
+ */
+ public void testConstructorBytesPositive3() {
+ byte aBytes[] = {127, 56, 100, -1};
+ byte rBytes[] = {127, 56, 100, -1};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from an array of bytes.
+ * The number of bytes is multiple of 4.
+ */
+ public void testConstructorBytesPositive() {
+ byte aBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+ byte rBytes[] = {127, 56, 100, -1, 14, 75, -24, -100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes.
+ * The number fits in an array of integers.
+ */
+ public void testConstructorBytesNegative1() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ byte rBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes.
+ * The number fits in an integer.
+ */
+ public void testConstructorBytesNegative2() {
+ byte aBytes[] = {-12, 56, 100};
+ byte rBytes[] = {-12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes.
+ * The number of bytes is 4.
+ */
+ public void testConstructorBytesNegative3() {
+ byte aBytes[] = {-128, -12, 56, 100};
+ byte rBytes[] = {-128, -12, 56, 100};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from an array of bytes.
+ * The number of bytes is multiple of 4.
+ */
+ public void testConstructorBytesNegative4() {
+ byte aBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+ byte rBytes[] = {-128, -12, 56, 100, -13, 56, 93, -78};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from an array of zero bytes.
+ */
+ public void testConstructorBytesZero() {
+ byte aBytes[] = {0, 0, 0, -0, +0, 0, -0};
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a number from a sign and an array of bytes.
+ * Verify an exception thrown if a sign has improper value.
+ */
+ public void testConstructorSignBytesException1() {
+ byte aBytes[] = {123, 45, -3, -76};
+ int aSign = 3;
+ try {
+ new BigInteger(aSign, aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a sign and an array of bytes.
+ * Verify an exception thrown if the array contains non-zero bytes while the sign is 0.
+ */
+ public void testConstructorSignBytesException2() {
+ byte aBytes[] = {123, 45, -3, -76};
+ int aSign = 0;
+ try {
+ new BigInteger(aSign, aBytes);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ assertEquals("Improper exception message", "signum-magnitude mismatch", e.getMessage());
+ }
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number fits in an array of integers.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number fits in an array of integers.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive2() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number fits in an integer.
+ */
+ public void testConstructorSignBytesPositive3() {
+ byte aBytes[] = {-12, 56, 100};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number of bytes is 4.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive4() {
+ byte aBytes[] = {127, 56, 100, -2};
+ int aSign = 1;
+ byte rBytes[] = {127, 56, 100, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number of bytes is 4.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive5() {
+ byte aBytes[] = {-127, 56, 100, -2};
+ int aSign = 1;
+ byte rBytes[] = {0, -127, 56, 100, -2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number of bytes is multiple of 4.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesPositive6() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = 1;
+ byte rBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a sign and an array of bytes.
+ * The number of bytes is multiple of 4.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesPositive7() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = 1;
+ byte rBytes[] = {0, -12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number fits in an array of integers.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = -1;
+ byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number fits in an array of integers.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative2() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 15};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number fits in an integer.
+ */
+ public void testConstructorSignBytesNegative3() {
+ byte aBytes[] = {-12, 56, 100};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -100};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number of bytes is 4.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative4() {
+ byte aBytes[] = {127, 56, 100, -2};
+ int aSign = -1;
+ byte rBytes[] = {-128, -57, -101, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number of bytes is 4.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative5() {
+ byte aBytes[] = {-127, 56, 100, -2};
+ int aSign = -1;
+ byte rBytes[] = {-1, 126, -57, -101, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number of bytes is multiple of 4.
+ * The most significant byte is positive.
+ */
+ public void testConstructorSignBytesNegative6() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = -1;
+ byte rBytes[] = {-13, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a sign and an array of bytes.
+ * The number of bytes is multiple of 4.
+ * The most significant byte is negative.
+ */
+ public void testConstructorSignBytesNegative7() {
+ byte aBytes[] = {-12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 23, -101};
+ int aSign = -1;
+ byte rBytes[] = {-1, 11, -57, -101, 1, 75, -90, -46, -92, -4, 14, -24, 101};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes.
+ * The sign is -1.
+ */
+ public void testConstructorSignBytesZero1() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes.
+ * The sign is 0.
+ */
+ public void testConstructorSignBytesZero2() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero bytes.
+ * The sign is 1.
+ */
+ public void testConstructorSignBytesZero3() {
+ byte aBytes[] = {-0, 0, +0, 0, 0, 00, 000};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length.
+ * The sign is -1.
+ */
+ public void testConstructorSignBytesZeroNull1() {
+ byte aBytes[] = {};
+ int aSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length.
+ * The sign is 0.
+ */
+ public void testConstructorSignBytesZeroNull2() {
+ byte aBytes[] = {};
+ int aSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a sign and an array of zero length.
+ * The sign is 1.
+ */
+ public void testConstructorSignBytesZeroNull3() {
+ byte aBytes[] = {};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a number from a string value and radix.
+ * Verify an exception thrown if a radix is out of range
+ */
+ public void testConstructorStringException1() {
+ String value = "9234853876401";
+ int radix = 45;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix.
+ * Verify an exception thrown if the string starts with a space.
+ */
+ public void testConstructorStringException2() {
+ String value = " 9234853876401";
+ int radix = 10;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix.
+ * Verify an exception thrown if the string contains improper characters.
+ */
+ public void testConstructorStringException3() {
+ String value = "92348$*#78987";
+ int radix = 34;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a number from a string value and radix.
+ * Verify an exception thrown if some digits are greater than radix.
+ */
+ public void testConstructorStringException4() {
+ String value = "98zv765hdsaiy";
+ int radix = 20;
+ try {
+ new BigInteger(value, radix);
+ fail("NumberFormatException has not been caught");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * Create a positive number from a string value and radix 2.
+ */
+ public void testConstructorStringRadix2() {
+ String value = "10101010101010101";
+ int radix = 2;
+ byte rBytes[] = {1, 85, 85};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 8.
+ */
+ public void testConstructorStringRadix8() {
+ String value = "76356237071623450";
+ int radix = 8;
+ byte rBytes[] = {7, -50, -28, -8, -25, 39, 40};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 10.
+ */
+ public void testConstructorStringRadix10() {
+ String value = "987328901348934898";
+ int radix = 10;
+ byte rBytes[] = {13, -77, -78, 103, -103, 97, 68, -14};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 16.
+ */
+ public void testConstructorStringRadix16() {
+ String value = "fe2340a8b5ce790";
+ int radix = 16;
+ byte rBytes[] = {15, -30, 52, 10, -117, 92, -25, -112};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a positive number from a string value and radix 36.
+ */
+ public void testConstructorStringRadix36() {
+ String value = "skdjgocvhdjfkl20jndjkf347ejg457";
+ int radix = 36;
+ byte rBytes[] = {0, -12, -116, 112, -105, 12, -36, 66, 108, 66, -20, -37, -15, 108, -7, 52, -99, -109, -8, -45, -5};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * Create a negative number from a string value and radix 10.
+ */
+ public void testConstructorStringRadix10Negative() {
+ String value = "-234871376037";
+ int radix = 36;
+ byte rBytes[] = {-4, 48, 71, 62, -76, 93, -105, 13};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * Create a zero number from a string value and radix 36.
+ */
+ public void testConstructorStringRadix10Zero() {
+ String value = "-00000000000000";
+ int radix = 10;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(value, radix);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+
+ /**
+ * Create a random number of 75 bits length.
+ */
+ public void testConstructorRandom() {
+ int bitLen = 75;
+ Random rnd = new Random();
+ BigInteger aNumber = new BigInteger(bitLen, rnd);
+ assertTrue("incorrect bitLength", aNumber.bitLength() <= bitLen);
+ }
+
+ public void testConstructorPrime() {
+ for (int rep = 0; rep < 2048; ++rep) {
+ Random rnd = new Random();
+ BigInteger b;
+ int bits;
+
+ // Create a 128-bit prime number.
+ bits = 128;
+ b = new BigInteger(bits, 10, rnd);
+ assertEquals(b.toString(), bits, b.bitLength());
+
+ // Create a prime number of 25 bits length.
+ bits = 25;
+ b = new BigInteger(bits, 10, rnd);
+ assertEquals(b.toString(), bits, b.bitLength());
+
+ // Create a prime number of 18 bits length.
+ bits = 18;
+ b = new BigInteger(bits, 10, rnd);
+ assertEquals(b.toString(), bits, b.bitLength());
+
+ // On Android, anything less than 16 bits used to be at least 16 bits
+ // because that's how OpenSSL behaves, but we recently fixed this...
+ bits = 2;
+ b = new BigInteger(bits, 10, rnd);
+ assertEquals(b.toString(), bits, b.bitLength());
+
+ // The 2-arg constructor has never used OpenSSL.
+ bits = 2;
+ b = new BigInteger(bits, rnd);
+ assertTrue(b.toString(), b.bitLength() <= bits);
+ assertTrue(b.toString(), b.intValue() <= 3);
+
+ bits = 16;
+ b = new BigInteger(bits, rnd);
+ assertTrue(b.toString(), b.bitLength() <= bits);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.java
new file mode 100644
index 0000000..d72923d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerConvertTest.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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: intValue, longValue, toByteArray(), valueOf(long val),
+ * floatValue(), doubleValue()
+ */
+public class BigIntegerConvertTest extends TestCase {
+ /**
+ * Return the double value of ZERO.
+ */
+ public void testDoubleValueZero() {
+ String a = "0";
+ double result = 0.0;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The number's length is less than 64 bits.
+ */
+ public void testDoubleValuePositive1() {
+ String a = "27467238945";
+ double result = 2.7467238945E10;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The number's bit length is inside [63, 1024].
+ */
+ public void testDoubleValuePositive2() {
+ String a = "2746723894572364578265426346273456972";
+ double result = 2.7467238945723645E36;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a double value.
+ * The number's bit length is less than 64 bits.
+ */
+ public void testDoubleValueNegative1() {
+ String a = "-27467238945";
+ double result = -2.7467238945E10;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a double value.
+ * The number's bit length is inside [63, 1024].
+ */
+ public void testDoubleValueNegative2() {
+ String a = "-2746723894572364578265426346273456972";
+ double result = -2.7467238945723645E36;
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 1.
+ */
+ public void testDoubleValuePosRounded1() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.54747264387948E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 0
+ * but some of dropped bits are 1s.
+ */
+ public void testDoubleValuePosRounded2() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.547472643879479E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is NOT needed.
+ */
+ public void testDoubleValuePosNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+ int aSign = 1;
+ double result = 1.5474726438794828E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is needed.
+ */
+ public void testDoubleValueNegRounded1() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.54747264387948E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 0
+ * but some of dropped bits are 1s.
+ */
+ public void testDoubleValueNegRounded2() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 36, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.547472643879479E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * Rounding is NOT needed.
+ */
+ public void testDoubleValueNegNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, -128, 23, 1, -3, -5};
+ int aSign = -1;
+ double result = -1.5474726438794828E26;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The rounding bit is 0.
+ * The result is Double.MAX_VALUE.
+ */
+ public void testDoubleValuePosMaxValue() {
+ byte[] a = {0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ int aSign = 1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.MAX_VALUE);
+ }
+
+ /**
+ * Convert a negative number to a double value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The result is -Double.MAX_VALUE.
+ */
+ public void testDoubleValueNegMaxValue() {
+ byte[] a = {0, -1, -1, -1, -1, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == -Double.MAX_VALUE);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The rounding bit is 1.
+ * The result is Double.POSITIVE_INFINITY.
+ */
+ public void testDoubleValuePositiveInfinity1() {
+ byte[] a = {-1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int aSign = 1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The number's bit length is greater than 1024.
+ */
+ public void testDoubleValuePositiveInfinity2() {
+ String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == Double.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a double value.
+ * The number's bit length is greater than 1024.
+ */
+ public void testDoubleValueNegativeInfinity1() {
+ String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ double aNumber = new BigInteger(a).doubleValue();
+ assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a double value.
+ * The exponent is 1023 and the mantissa is all 0s.
+ * The rounding bit is 0.
+ * The result is Double.NEGATIVE_INFINITY.
+ */
+ public void testDoubleValueNegativeInfinity2() {
+ byte[] a = {-1, -1, -1, -1, -1, -1, -1, -8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == Double.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The exponent is 1023 and the mantissa is all 0s
+ * but the 54th bit (implicit) is 1.
+ */
+ public void testDoubleValuePosMantissaIsZero() {
+ byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int aSign = 1;
+ double result = 8.98846567431158E307;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The exponent is 1023 and the mantissa is all 0s
+ * but the 54th bit (implicit) is 1.
+ */
+ public void testDoubleValueNegMantissaIsZero() {
+ byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int aSign = -1;
+ double aNumber = new BigInteger(aSign, a).doubleValue();
+ assertTrue(aNumber == -8.98846567431158E307);
+ }
+
+ /**
+ * Return the float value of ZERO.
+ */
+ public void testFloatValueZero() {
+ String a = "0";
+ float result = 0.0f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The number's length is less than 32 bits.
+ */
+ public void testFloatValuePositive1() {
+ String a = "27467238";
+ float result = 2.7467238E7f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The number's bit length is inside [32, 127].
+ */
+ public void testFloatValuePositive2() {
+ String a = "27467238945723645782";
+ float result = 2.7467239E19f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a float value.
+ * The number's bit length is less than 32 bits.
+ */
+ public void testFloatValueNegative1() {
+ String a = "-27467238";
+ float result = -2.7467238E7f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative number to a doufloatble value.
+ * The number's bit length is inside [63, 1024].
+ */
+ public void testFloatValueNegative2() {
+ String a = "-27467238945723645782";
+ float result = -2.7467239E19f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 1.
+ */
+ public void testFloatValuePosRounded1() {
+ byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5475195E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 0
+ * but some of dropped bits are 1s.
+ */
+ public void testFloatValuePosRounded2() {
+ byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5474728E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is NOT needed.
+ */
+ public void testFloatValuePosNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = 1;
+ float result = 1.5474726E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is needed.
+ */
+ public void testFloatValueNegRounded1() {
+ byte[] a = {-128, 1, -1, -4, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5475195E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is needed.
+ * The rounding bit is 1 and the next bit to the left is 0
+ * but some of dropped bits are 1s.
+ */
+ public void testFloatValueNegRounded2() {
+ byte[] a = {-128, 1, 2, -128, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5474728E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * Rounding is NOT needed.
+ */
+ public void testFloatValueNegNotRounded() {
+ byte[] a = {-128, 1, 2, 3, 4, 5, 60, 23, 1, -3, -5};
+ int aSign = -1;
+ float result = -1.5474726E26f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The rounding bit is 0.
+ * The result is Float.MAX_VALUE.
+ */
+ public void testFloatValuePosMaxValue() {
+ byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == Float.MAX_VALUE);
+ }
+
+ /**
+ * Convert a negative number to a float value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The rounding bit is 0.
+ * The result is -Float.MAX_VALUE.
+ */
+ public void testFloatValueNegMaxValue() {
+ byte[] a = {0, -1, -1, -1, 0, -1, -1, -8, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == -Float.MAX_VALUE);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The exponent is 1023 and the mantissa is all 1s.
+ * The rounding bit is 1.
+ * The result is Float.POSITIVE_INFINITY.
+ */
+ public void testFloatValuePositiveInfinity1() {
+ byte[] a = {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = 1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == Float.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The number's bit length is greater than 127.
+ */
+ public void testFloatValuePositiveInfinity2() {
+ String a = "2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == Float.POSITIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a float value.
+ * The number's bit length is greater than 127.
+ */
+ public void testFloatValueNegativeInfinity1() {
+ String a = "-2746723894572364578265426346273456972283746872364768676747462342342342342342342342323423423423423423426767456345745293762384756238475634563456845634568934568347586346578648576478568456457634875673845678456786587345873645767456834756745763457863485768475678465783456702897830296720476846578634576384567845678346573465786457863";
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a float value.
+ * The exponent is 1023 and the mantissa is all 0s.
+ * The rounding bit is 0.
+ * The result is Float.NEGATIVE_INFINITY.
+ */
+ public void testFloatValueNegativeInfinity2() {
+ byte[] a = {0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a positive number to a float value.
+ * The exponent is 1023 and the mantissa is all 0s
+ * but the 54th bit (implicit) is 1.
+ */
+ public void testFloatValuePosMantissaIsZero() {
+ byte[] a = {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ float result = 1.7014118E38f;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive number to a double value.
+ * The exponent is 1023 and the mantissa is all 0s
+ * but the 54th bit (implicit) is 1.
+ */
+ public void testFloatValueNegMantissaIsZero() {
+ byte[] a = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ float aNumber = new BigInteger(aSign, a).floatValue();
+ assertTrue(aNumber == Float.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * Convert a negative number to a float value.
+ * The number's bit length is less than 32 bits.
+ */
+ public void testFloatValueBug2482() {
+ String a = "2147483649";
+ float result = 2.14748365E9f;
+ float aNumber = new BigInteger(a).floatValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value.
+ * The low digit is positive
+ */
+ public void testIntValuePositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3};
+ int resInt = 1496144643;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertTrue(aNumber == resInt);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value.
+ * The low digit is positive
+ */
+ public void testIntValuePositive2() {
+ byte aBytes[] = {12, 56, 100};
+ int resInt = 800868;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertTrue(aNumber == resInt);
+ }
+
+ /**
+ * Convert a positive BigInteger to an integer value.
+ * The low digit is negative.
+ */
+ public void testIntValuePositive3() {
+ byte aBytes[] = {56, 13, 78, -12, -5, 56, 100};
+ int sign = 1;
+ int resInt = -184862620;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertTrue(aNumber == resInt);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value.
+ * The low digit is negative.
+ */
+ public void testIntValueNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, -128, 45, 91, 3};
+ int sign = -1;
+ int resInt = 2144511229;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertTrue(aNumber == resInt);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value.
+ * The low digit is negative.
+ */
+ public void testIntValueNegative2() {
+ byte aBytes[] = {-12, 56, 100};
+ int result = -771996;
+ int aNumber = new BigInteger(aBytes).intValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a negative BigInteger to an integer value.
+ * The low digit is positive.
+ */
+ public void testIntValueNegative3() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 127, 45, 91, 3};
+ int sign = -1;
+ int resInt = -2133678851;
+ int aNumber = new BigInteger(sign, aBytes).intValue();
+ assertTrue(aNumber == resInt);
+ }
+
+ /**
+ * Convert a BigInteger to a positive long value
+ * The BigInteger is longer than int.
+ */
+ public void testLongValuePositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, 120, -34, -12, 45, 98};
+ long result = 3268209772258930018L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a number to a positive long value
+ * The number fits in a long.
+ */
+ public void testLongValuePositive2() {
+ byte aBytes[] = {12, 56, 100, 18, -105, 34, -18, 45};
+ long result = 880563758158769709L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a number to a negative long value
+ * The BigInteger is longer than int.
+ */
+ public void testLongValueNegative1() {
+ byte aBytes[] = {12, -1, 100, -2, -76, -128, 45, 91, 3};
+ long result = -43630045168837885L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * Convert a number to a negative long value
+ * The number fits in a long.
+ */
+ public void testLongValueNegative2() {
+ byte aBytes[] = {-12, 56, 100, 45, -101, 45, 98};
+ long result = -3315696807498398L;
+ long aNumber = new BigInteger(aBytes).longValue();
+ assertTrue(aNumber == result);
+ }
+
+ /**
+ * valueOf (long val): convert Integer.MAX_VALUE to a BigInteger.
+ */
+ public void testValueOfIntegerMax() {
+ long longVal = Integer.MAX_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {127, -1, -1, -1};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Integer.MIN_VALUE to a BigInteger.
+ */
+ public void testValueOfIntegerMin() {
+ long longVal = Integer.MIN_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-128, 0, 0, 0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Long.MAX_VALUE to a BigInteger.
+ */
+ public void testValueOfLongMax() {
+ long longVal = Long.MAX_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {127, -1, -1, -1, -1, -1, -1, -1};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert Long.MIN_VALUE to a BigInteger.
+ */
+ public void testValueOfLongMin() {
+ long longVal = Long.MIN_VALUE;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-128, 0, 0, 0, 0, 0, 0, 0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a positive long value to a BigInteger.
+ */
+ public void testValueOfLongPositive1() {
+ long longVal = 268209772258930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {3, -72, -33, 93, -24, -56, 45, 98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a positive long value to a BigInteger.
+ * The long value fits in integer.
+ */
+ public void testValueOfLongPositive2() {
+ long longVal = 58930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {3, -125, 51, 98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a negative long value to a BigInteger.
+ */
+ public void testValueOfLongNegative1() {
+ long longVal = -268209772258930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-4, 71, 32, -94, 23, 55, -46, -98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+
+ /**
+ * valueOf (long val): convert a negative long value to a BigInteger.
+ * The long value fits in integer.
+ */
+ public void testValueOfLongNegative2() {
+ long longVal = -58930018L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {-4, 124, -52, -98};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, aNumber.signum());
+ }
+ /**
+ * valueOf (long val): convert a zero long value to a BigInteger.
+ */
+ public void testValueOfLongZero() {
+ long longVal = 0L;
+ BigInteger aNumber = BigInteger.valueOf(longVal);
+ byte rBytes[] = {0};
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = aNumber.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, aNumber.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java
new file mode 100644
index 0000000..3f2ab51
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerDivideTest.java
@@ -0,0 +1,666 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: divide, remainder, mod, and divideAndRemainder
+ */
+public class BigIntegerDivideTest extends TestCase {
+ /**
+ * Divide by zero
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * Divide by ZERO
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ try {
+ aNumber.divide(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * Divide two equal positive numbers
+ */
+ public void testCase3() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide two equal in absolute value numbers of different signs.
+ */
+ public void testCase4() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide two numbers of different length and different signs.
+ * The second is longer.
+ */
+ public void testCase5() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 1, 2, 3, 4, 5};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide two positive numbers of the same length.
+ * The second is greater.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {15, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide two positive numbers.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {23, 115, 11, 78, 35, -11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide a positive number by a negative one.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide a negative number by a positive one.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-24, -116, -12, -79, -36, 11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide two negative numbers.
+ */
+ public void testCase10() {
+ byte aBytes[] = {1, 100, 56, 7, 98, -1, 39, -128, 127, 5, 6, 7, 8, 9};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {23, 115, 11, 78, 35, -11};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide zero by a negative number.
+ */
+ public void testCase11() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide ZERO by a negative number.
+ */
+ public void testCase12() {
+ byte bBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int bSign = -1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Divide a positive number by ONE.
+ */
+ public void testCase13() {
+ byte aBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ int aSign = 1;
+ byte rBytes[] = {15, 48, -29, 7, 98, -1, 39, -128};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide ONE by ONE.
+ */
+ public void testCase14() {
+ byte rBytes[] = {1};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Verifies the case when borrow != 0 in the private divide method.
+ */
+ public void testDivisionKnuth1() {
+ byte aBytes[] = {-7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {-3, -3, -3, -3};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -5, -12, -33, -96, -36, -105, -56, 92, 15, 48, -109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Verifies the case when the divisor is already normalized.
+ */
+ public void testDivisionKnuthIsNormalized() {
+ byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+ byte bBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {0, -9, -8, -7, -6, -5, -4, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Verifies the case when the first digits of the dividend
+ * and divisor equal.
+ */
+ public void testDivisionKnuthFirstDigitsEqual() {
+ byte aBytes[] = {2, -3, -4, -5, -1, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5};
+ byte bBytes[] = {2, -3, -4, -5, -1, -1, -1, -1};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {0, -1, -1, -1, -1, -2, -88, -60, 41};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of one digit by the number of one digit
+ */
+ public void testDivisionKnuthOneDigitByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5};
+ byte bBytes[] = {2, -3, -4, -5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Divide the number of multi digits by the number of one digit
+ */
+ public void testDivisionKnuthMultiDigitsByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+ byte bBytes[] = {2, -3, -4, -5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-38, 2, 7, 30, 109, -43};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.divide(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Remainder of division by zero
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.remainder(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * Remainder of division of equal numbers
+ */
+ public void testCase16() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ byte bBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Remainder of division of two positive numbers
+ */
+ public void testCase17() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Remainder of division of two negative numbers
+ */
+ public void testCase18() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-13, 20, -74, -57, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Remainder of division of two numbers of different signs.
+ * The first is positive.
+ */
+ public void testCase19() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Remainder of division of two numbers of different signs.
+ * The first is negative.
+ */
+ public void testCase20() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-13, 20, -74, -57, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Tests the step D6 from the Knuth algorithm
+ */
+ public void testRemainderKnuth1() {
+ byte aBytes[] = {-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1};
+ byte bBytes[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 7, 18, -89};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of one digit by the number of one digit
+ */
+ public void testRemainderKnuthOneDigitByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5};
+ byte bBytes[] = {2, -3, -4, -50};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {2, -9, -14, 53};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Divide the number of multi digits by the number of one digit
+ */
+ public void testRemainderKnuthMultiDigitsByOneDigit() {
+ byte aBytes[] = {113, -83, 123, -5, 18, -34, 67, 39, -29};
+ byte bBytes[] = {2, -3, -4, -50};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {2, -37, -60, 59};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.remainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * divideAndRemainder of two numbers of different signs.
+ * The first is negative.
+ */
+ public void testCase21() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[][] = {
+ {-5, 94, -115, -74, -85, 84},
+ {-13, 20, -74, -57, -27}
+ };
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result[] = aNumber.divideAndRemainder(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result[0].toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ if (resBytes[i] != rBytes[0][i]) {
+ fail("Incorrect quotation");
+ }
+ }
+ assertEquals(-1, result[0].signum());
+ resBytes = result[1].toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ if (resBytes[i] != rBytes[1][i]) {
+ fail("Incorrect remainder");
+ }
+ assertEquals(-1, result[1].signum());
+ }
+ }
+
+ /**
+ * mod when modulus is negative
+ */
+ public void testCase22() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {1, 30, 40, 56, -1, 45};
+ int aSign = 1;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ try {
+ aNumber.mod(bNumber);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * mod when a divisor is positive
+ */
+ public void testCase23() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {12, -21, 73, 56, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.mod(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * mod when a divisor is negative
+ */
+ public void testCase24() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75};
+ byte bBytes[] = {27, -15, 65, 39, 100};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {15, 5, -9, -17, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.mod(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java
new file mode 100644
index 0000000..52bf56f
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerHashCodeTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: hashCode()
+ */
+public class BigIntegerHashCodeTest extends TestCase {
+ /**
+ * Test hash codes for the same object
+ */
+ public void testSameObject() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ aNumber1.add(aNumber2).shiftLeft(125);
+ aNumber1.subtract(aNumber2).shiftRight(125);
+ aNumber1.multiply(aNumber2).toByteArray();
+ aNumber1.divide(aNumber2).bitLength();
+ aNumber1.gcd(aNumber2).pow(7);
+ int code2 = aNumber1.hashCode();
+ assertTrue("hash codes for the same object differ", code1 == code2);
+ }
+
+ /**
+ * Test hash codes for equal objects.
+ */
+ public void testEqualObjects() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "12378246728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ int code2 = aNumber2.hashCode();
+ if (aNumber1.equals(aNumber2)) {
+ assertTrue("hash codes for equal objects are unequal", code1 == code2);
+ }
+ }
+
+ /**
+ * Test hash codes for unequal objects.
+ * The codes are unequal.
+ */
+ public void testUnequalObjectsUnequal() {
+ String value1 = "12378246728727834290276457386374882976782849";
+ String value2 = "-5634562095872038262928728727834290276457386374882976782849";
+ BigInteger aNumber1 = new BigInteger(value1);
+ BigInteger aNumber2 = new BigInteger(value2);
+ int code1 = aNumber1.hashCode();
+ int code2 = aNumber2.hashCode();
+ if (!aNumber1.equals(aNumber2)) {
+ assertTrue("hash codes for unequal objects are equal", code1 != code2);
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java
new file mode 100644
index 0000000..4af4d9d
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerModPowTest.java
@@ -0,0 +1,351 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: modPow, modInverse, and gcd
+ */
+public class BigIntegerModPowTest extends TestCase {
+ /**
+ * modPow: non-positive modulus
+ */
+ public void testModPowException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte eBytes[] = {1, 2, 3, 4, 5};
+ byte mBytes[] = {1, 2, 3};
+ int aSign = 1;
+ int eSign = 1;
+ int mSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modPow(exp, modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ BigInteger.ZERO.modPow(new BigInteger("-1"), new BigInteger("10"));
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ // expected
+ }
+ }
+
+ /**
+ * modPow: positive exponent
+ */
+ public void testModPowPosExp() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+ byte eBytes[] = {27, -15, 65, 39};
+ byte mBytes[] = {-128, 2, 3, 4, 5};
+ int aSign = 1;
+ int eSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {113, 100, -84, -28, -85};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modPow(exp, modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modPow: negative exponent
+ */
+ public void testModPowNegExp() {
+ byte aBytes[] = {-127, 100, 56, 7, 98, -1, 39, -128, 127, 75, 48, -7};
+ byte eBytes[] = {27, -15, 65, 39};
+ byte mBytes[] = {-128, 2, 3, 4, 5};
+ int aSign = 1;
+ int eSign = -1;
+ int mSign = 1;
+ byte rBytes[] = {12, 118, 46, 86, 92};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger exp = new BigInteger(eSign, eBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modPow(exp, modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ public void testModPowZeroExp() {
+ BigInteger exp = new BigInteger("0");
+ BigInteger[] base = new BigInteger[] {new BigInteger("-1"), new BigInteger("0"), new BigInteger("1")};
+ BigInteger[] mod = new BigInteger[] {new BigInteger("2"), new BigInteger("10"), new BigInteger("2147483648")};
+
+ for (int i = 0; i < base.length; ++i) {
+ for (int j = 0; j < mod.length; ++j) {
+ assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
+ + ") should be " + BigInteger.ONE, BigInteger.ONE,
+ base[i].modPow(exp, mod[j]));
+ }
+ }
+
+ mod = new BigInteger[] {new BigInteger("1")};
+ for (int i = 0; i < base.length; ++i) {
+ for (int j = 0; j < mod.length; ++j) {
+ assertEquals(base[i] + " modePow(" + exp + ", " + mod[j]
+ + ") should be " + BigInteger.ZERO, BigInteger.ZERO,
+ base[i].modPow(exp, mod[j]));
+ }
+ }
+ }
+
+ /**
+ * modInverse: non-positive modulus
+ */
+ public void testmodInverseException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ byte mBytes[] = {1, 2, 3};
+ int aSign = 1;
+ int mSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modInverse(modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * modInverse: non-invertible number
+ */
+ public void testmodInverseNonInvertible() {
+ byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte mBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ int aSign = 1;
+ int mSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ try {
+ aNumber.modInverse(modulus);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * modInverse: positive number
+ */
+ public void testmodInversePos1() {
+ byte aBytes[] = {24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte mBytes[] = {122, 45, 36, 100, 122, 45};
+ int aSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {47, 3, 96, 62, 87, 19};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: positive number (another case: a < 0)
+ */
+ public void testmodInversePos2() {
+ byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte mBytes[] = {2, 122, 45, 36, 100};
+ int aSign = 1;
+ int mSign = 1;
+ byte rBytes[] = {1, -93, 40, 127, 73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: negative number
+ */
+ public void testmodInverseNeg1() {
+ byte aBytes[] = {15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte mBytes[] = {2, 122, 45, 36, 100};
+ int aSign = -1;
+ int mSign = 1;
+ byte rBytes[] = {0, -41, 4, -91, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger modulus = new BigInteger(mSign, mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * modInverse: negative number (another case: x < 0)
+ */
+ public void testmodInverseNeg2() {
+ byte aBytes[] = {-15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ byte mBytes[] = {122, 2, 4, 122, 2, 4};
+ byte rBytes[] = {85, 47, 127, 4, -128, 45};
+ BigInteger aNumber = new BigInteger(aBytes);
+ BigInteger modulus = new BigInteger(mBytes);
+ BigInteger result = aNumber.modInverse(modulus);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the second number is zero
+ */
+ public void testGcdSecondZero() {
+ byte aBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the first number is zero
+ */
+ public void testGcdFirstZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the first number is ZERO
+ */
+ public void testGcdFirstZERO() {
+ byte bBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ int bSign = 1;
+ byte rBytes[] = {15, 24, 123, 57, -15, 24, 123, 57, -15, 24, 123, 57};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: both numbers are zeros
+ */
+ public void testGcdBothZeros() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger("0");
+ BigInteger bNumber = BigInteger.valueOf(0L);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * gcd: the first number is longer
+ */
+ public void testGcdFirstLonger() {
+ byte aBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ byte bBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * gcd: the second number is longer
+ */
+ public void testGcdSecondLonger() {
+ byte aBytes[] = {-12, 1, 0, 0, 0, 23, 44, 55, 66};
+ byte bBytes[] = {-15, 24, 123, 56, -11, -112, -34, -98, 8, 10, 12, 14, 25, 125, -15, 28, -127};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {7};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.gcd(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java
new file mode 100644
index 0000000..0bfcbf0
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerMultiplyTest.java
@@ -0,0 +1,388 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: multiply
+ */
+public class BigIntegerMultiplyTest extends TestCase {
+ /**
+ * Multiply two negative numbers of the same length
+ */
+ public void testCase1() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 105, 4, 28, -86, -117, -52, 100, 120, 90};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of the same length and different signs.
+ * The first is negative.
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -106, -5, -29, 85, 116, 51, -101, -121, -90};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two positive numbers of different length.
+ * The first is longer.
+ */
+ public void testCase3() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127,
+ 115, -21, -62, -15, 85, 64, -87, -2, -36, -36, -106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two positive numbers of different length.
+ * The second is longer.
+ */
+ public void testCase4() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {10, 40, 100, -55, 96, 51, 76, 40, -45, 85, 115, 44, -127,
+ 115, -21, -62, -15, 85, 64, -87, -2, -36, -36, -106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of different length and different signs.
+ * The first is positive.
+ * The first is longer.
+ */
+ public void testCase5() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126,
+ -116, 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of different length and different signs.
+ * The first is positive.
+ * The second is longer.
+ */
+ public void testCase6() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-11, -41, -101, 54, -97, -52, -77, -41, 44, -86, -116, -45, 126,
+ -116, 20, 61, 14, -86, -65, 86, 1, 35, 35, 106};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply a number by zero.
+ */
+ public void testCase7() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Multiply a number by ZERO.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Multiply a positive number by ONE.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = 1;
+ byte rBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Multiply a negative number by ONE.
+ */
+ public void testCase10() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 1, 2, 3, 4, 5};
+ int aSign = -1;
+ byte rBytes[] = {-2, -3, -4, -5, -6, -7, -8, -2, -3, -4, -2, -3, -4, -5, -5};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of 4 bytes length.
+ */
+ public void testIntbyInt1() {
+ byte aBytes[] = {10, 20, 30, 40};
+ byte bBytes[] = {1, 2, 3, 4};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-11, -41, -101, 55, 5, 15, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Multiply two numbers of 4 bytes length.
+ */
+ public void testIntbyInt2() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ byte bBytes[] = {-1, -1, -1, -1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -1, -1, -1, -2, 0, 0, 0, 1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.multiply(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Negative exponent.
+ */
+ public void testPowException() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int exp = -5;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.pow(exp);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * Exponentiation of a negative number to an odd exponent.
+ */
+ public void testPowNegativeNumToOddExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 5;
+ byte rBytes[] = {-21, -94, -42, -15, -127, 113, -50, -88, 115, -35, 3,
+ 59, -92, 111, -75, 103, -42, 41, 34, -114, 99, -32, 105, -59, 127,
+ 45, 108, 74, -93, 105, 33, 12, -5, -20, 17, -21, -119, -127, -115,
+ 27, -122, 26, -67, 109, -125, 16, 91, -70, 109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to an even exponent.
+ */
+ public void testPowNegativeNumToEvenExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 4;
+ byte rBytes[] = {102, 107, -122, -43, -52, -20, -27, 25, -9, 88, -13,
+ 75, 78, 81, -33, -77, 39, 27, -37, 106, 121, -73, 108, -47, -101,
+ 80, -25, 71, 13, 94, -7, -33, 1, -17, -65, -70, -61, -3, -47};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to zero exponent.
+ */
+ public void testPowNegativeNumToZeroExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = -1;
+ int exp = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a positive number.
+ */
+ public void testPowPositiveNum() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = 1;
+ int exp = 5;
+ byte rBytes[] = {20, 93, 41, 14, 126, -114, 49, 87, -116, 34, -4, -60,
+ 91, -112, 74, -104, 41, -42, -35, 113, -100, 31, -106, 58, -128,
+ -46, -109, -75, 92, -106, -34, -13, 4, 19, -18, 20, 118, 126, 114,
+ -28, 121, -27, 66, -110, 124, -17, -92, 69, -109};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Exponentiation of a negative number to zero exponent.
+ */
+ public void testPowPositiveNumToZeroExp() {
+ byte aBytes[] = {50, -26, 90, 69, 120, 32, 63, -103, -14, 35};
+ int aSign = 1;
+ int exp = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.pow(exp);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java
new file mode 100644
index 0000000..615afc1
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerNotTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: and, andNot
+ */
+public class BigIntegerNotTest extends TestCase {
+ /**
+ * andNot for two positive numbers; the first is longer
+ */
+ public void testAndNotPosPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 9, 56, 100, 0, 0, 1, 1, 90, 1, -32, 0, 10, -126, 21, 82, -31, -96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for two positive numbers; the first is shorter
+ */
+ public void testAndNotPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for two negative numbers; the first is longer
+ */
+ public void testAndNotNegNegFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {73, -92, -48, 4, 12, 6, 4, 32, 48, 64, 0, 8, 2};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * andNot for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1, 127, -10, -57, -101, 1, 2, 2, 2, -96, -16, 8, -40, -59, 68, -88, -88, 16, 72};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.andNot(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for ZERO
+ */
+ public void testNotZero() {
+ byte rBytes[] = {-1};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for ONE
+ */
+ public void testNotOne() {
+ byte rBytes[] = {-2};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for a positive number
+ */
+ public void testNotPos() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ int aSign = 1;
+ byte rBytes[] = {-1, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -27, 116};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Not for a negative number
+ */
+ public void testNotNeg() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ int aSign = -1;
+ byte rBytes[] = {0, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -118};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Not for a negative number
+ */
+
+ public void testNotSpecialCase() {
+ byte aBytes[] = {-1, -1, -1, -1};
+ int aSign = 1;
+ byte rBytes[] = {-1, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.not();
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+}
\ No newline at end of file
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
new file mode 100644
index 0000000..9b7c198
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOperateBitsTest.java
@@ -0,0 +1,1375 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Methods: bitLength, shiftLeft, shiftRight,
+ * clearBit, flipBit, setBit, testBit
+ */
+public class BigIntegerOperateBitsTest extends TestCase {
+ /**
+ * bitCount() of zero.
+ */
+ public void testBitCountZero() {
+ BigInteger aNumber = new BigInteger("0");
+ assertEquals(0, aNumber.bitCount());
+ }
+
+ /**
+ * bitCount() of a negative number.
+ */
+ public void testBitCountNeg() {
+ BigInteger aNumber = new BigInteger("-12378634756382937873487638746283767238657872368748726875");
+ assertEquals(87, aNumber.bitCount());
+ }
+
+ /**
+ * bitCount() of a negative number.
+ */
+ public void testBitCountPos() {
+ BigInteger aNumber = new BigInteger("12378634756343564757582937873487638746283767238657872368748726875");
+ assertEquals(107, aNumber.bitCount());
+ }
+
+ /**
+ * bitLength() of zero.
+ */
+ public void testBitLengthZero() {
+ BigInteger aNumber = new BigInteger("0");
+ assertEquals(0, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number.
+ */
+ public void testBitLengthPositive1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(108, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number with the leftmost bit set
+ */
+ public void testBitLengthPositive2() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(96, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a positive number which is a power of 2
+ */
+ public void testBitLengthPositive3() {
+ byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(81, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a negative number.
+ */
+ public void testBitLengthNegative1() {
+ byte aBytes[] = {12, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, 3, 91};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(108, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a negative number with the leftmost bit set
+ */
+ public void testBitLengthNegative2() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(96, aNumber.bitLength());
+ }
+
+ /**
+ * bitLength() of a negative number which is a power of 2
+ */
+ public void testBitLengthNegative3() {
+ byte aBytes[] = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertEquals(80, aNumber.bitLength());
+ }
+
+ /**
+ * clearBit(int n) of a negative n
+ */
+ public void testClearBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.clearBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * clearBit(int n) outside zero
+ */
+ public void testClearBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside zero
+ */
+ public void testClearBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 95;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a negative number
+ */
+ public void testClearBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a negative number
+ */
+ public void testClearBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 44;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -62, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(2) in the negative number with all ones in bit representation
+ */
+ public void testClearBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * clearBit(0) in the negative number of length 1
+ * with all ones in bit representation.
+ * the resulting number's length is 2.
+ */
+ public void testClearBitNegativeInside4() {
+ String as = "-4294967295";
+ String res = "-4294967296";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * clearBit(0) in the negative number of length 2
+ * with all ones in bit representation.
+ * the resulting number's length is 3.
+ */
+ public void testClearBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551616";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.clearBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * clearBit(int n) outside a negative number
+ */
+ public void testClearBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {-65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a negative number
+ */
+ public void testClearBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 165;
+ byte rBytes[] = {-33, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 20;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -31, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 17;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside4 () {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 50;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) inside a positive number
+ */
+ public void testClearBitPositiveInside5 () {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 63;
+ byte rBytes[] = {1, -128, 56, 100, -2, 52, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a positive number
+ */
+ public void testClearBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) outside a positive number
+ */
+ public void testClearBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 191;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * clearBit(int n) the leftmost bit in a negative number
+ */
+ public void testClearBitTopNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 63;
+ byte rBytes[] = {-1, 127, -2, 127, -57, -101, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.clearBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) of a negative n
+ */
+ public void testFlipBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.flipBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * flipBit(int n) zero
+ */
+ public void testFlipBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside zero
+ */
+ public void testFlipBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 62;
+ byte rBytes[] = {64, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside zero
+ */
+ public void testFlipBitZeroOutside2() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 63;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue("incorrect value", resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) the leftmost bit in a negative number
+ */
+ public void testFlipBitLeftmostNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 48;
+ byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) the leftmost bit in a positive number
+ */
+ public void testFlipBitLeftmostPositive() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = 1;
+ int number = 48;
+ byte rBytes[] = {0, -128, 56, 100, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number
+ */
+ public void testFlipBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, 92, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number
+ */
+ public void testFlipBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -14, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a negative number with all ones in bit representation
+ */
+ public void testFlipBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551611";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(0) in the negative number of length 1
+ * with all ones in bit representation.
+ * the resulting number's length is 2.
+ */
+ public void testFlipBitNegativeInside4() {
+ String as = "-4294967295";
+ String res = "-4294967296";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(0) in the negative number of length 2
+ * with all ones in bit representation.
+ * the resulting number's length is 3.
+ */
+ public void testFlipBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551616";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.flipBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * flipBit(int n) outside a negative number
+ */
+ public void testFlipBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {-65, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a negative number
+ */
+ public void testFlipBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 191;
+ byte rBytes[] = {-1, 127, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a positive number
+ */
+ public void testFlipBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 15;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, -93, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) inside a positive number
+ */
+ public void testFlipBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 13, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a positive number
+ */
+ public void testFlipBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * flipBit(int n) outside a positive number
+ */
+ public void testFlipBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 191;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.flipBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) of a negative n
+ */
+ public void testSetBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.setBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * setBit(int n) outside zero
+ */
+ public void testSetBitZero() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 0;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside zero
+ */
+ public void testSetBitZeroOutside1() {
+ byte aBytes[] = {0};
+ int aSign = 0;
+ int number = 95;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 20;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 17;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -13, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a positive number
+ */
+ public void testSetBitPositiveInside4 () {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 50;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 93, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a positive number
+ */
+ public void testSetBitPositiveOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 150;
+ byte rBytes[] = {64, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a positive number
+ */
+ public void testSetBitPositiveOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 223;
+ byte rBytes[] = {0, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) the leftmost bit in a positive number
+ */
+ public void testSetBitTopPositive() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = 1;
+ int number = 63;
+ byte rBytes[] = {0, -128, 1, -128, 56, 100, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * setBit(int n) the leftmost bit in a negative number
+ */
+ public void testSetBitLeftmostNegative() {
+ byte aBytes[] = {1, -128, 56, 100, -15, 35, 26};
+ int aSign = -1;
+ int number = 48;
+ byte rBytes[] = {-1, 127, -57, -101, 14, -36, -26, 49};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number
+ */
+ public void testSetBitNegativeInside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 15;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number
+ */
+ public void testSetBitNegativeInside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 44;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) inside a negative number with all ones in bit representation
+ */
+ public void testSetBitNegativeInside3() {
+ String as = "-18446744073709551615";
+ String res = "-18446744073709551611";
+ int number = 2;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(res, result.toString());
+ }
+
+ /**
+ * setBit(0) in the negative number of length 1
+ * with all ones in bit representation.
+ * the resulting number's length is 2.
+ */
+ public void testSetBitNegativeInside4() {
+ String as = "-4294967295";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * setBit(0) in the negative number of length 2
+ * with all ones in bit representation.
+ * the resulting number's length is 3.
+ */
+ public void testSetBitNegativeInside5() {
+ String as = "-18446744073709551615";
+ int number = 0;
+ BigInteger aNumber = new BigInteger(as);
+ BigInteger result = aNumber.setBit(number);
+ assertEquals(as, result.toString());
+ }
+
+ /**
+ * setBit(int n) outside a negative number
+ */
+ public void testSetBitNegativeOutside1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 150;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit(int n) outside a negative number
+ */
+ public void testSetBitNegativeOutside2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 191;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92, -4, 14, -36, -26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.setBit(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * setBit: check the case when the number of bit to be set can be
+ * represented as n * 32 + 31, where n is an arbitrary integer.
+ * Here 191 = 5 * 32 + 31
+ */
+ public void testSetBitBug1331() {
+ BigInteger result = BigInteger.valueOf(0L).setBit(191);
+ assertEquals("incorrect value", "3138550867693340381917894711603833208051177722232017256448", result.toString());
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n), n = 0
+ */
+ public void testShiftLeft1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 0;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n), n < 0
+ */
+ public void testShiftLeft2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -27;
+ byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a positive number, n > 0
+ */
+ public void testShiftLeft3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 27;
+ byte rBytes[] = {12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a positive number, n > 0
+ */
+ public void testShiftLeft4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96, 126, 36, 99, 64, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftLeft(int n) a negative number, n > 0
+ */
+ public void testShiftLeft5() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ byte rBytes[] = {-49, -8, -13, 96, 41, 116, -38, 84, -97, -127, -37, -100, -64, 0, 0, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftLeft(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n = 0
+ */
+ public void testShiftRight1() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 0;
+ byte rBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n < 0
+ */
+ public void testShiftRight2() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -27;
+ byte rBytes[] = {12, 1, -61, 39, -11, -94, -55, 106, -40, 31, -119, 24, -48, 0, 0, 0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), 0 < n < 32
+ */
+ public void testShiftRight3() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 27;
+ byte rBytes[] = {48, 7, 12, -97, -42, -117, 37, -85, 96};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n > 32
+ */
+ public void testShiftRight4() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ byte rBytes[] = {12, 1, -61, 39, -11, -94, -55};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * shiftRight(int n), n is greater than bitLength()
+ */
+ public void testShiftRight5() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 300;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number;
+ * shift distance is multiple of 32;
+ * shifted bits are NOT zeroes.
+ */
+ public void testShiftRightNegNonZeroesMul32() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 1, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 64;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -92};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number;
+ * shift distance is NOT multiple of 32;
+ * shifted bits are NOT zeroes.
+ */
+ public void testShiftRightNegNonZeroes() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 68;
+ byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 42};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number;
+ * shift distance is NOT multiple of 32;
+ * shifted bits are zeroes.
+ */
+ public void testShiftRightNegZeroes() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 68;
+ byte rBytes[] = {-25, -4, 121, -80, 20, -70, 109, 48};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * shiftRight a negative number;
+ * shift distance is multiple of 32;
+ * shifted bits are zeroes.
+ */
+ public void testShiftRightNegZeroesMul32() {
+ byte aBytes[] = {1, -128, 56, 100, -2, -76, 89, 45, 91, 0, 0, 0, 0, 0, 0, 0, 0};
+ int aSign = -1;
+ int number = 64;
+ byte rBytes[] = {-2, 127, -57, -101, 1, 75, -90, -46, -91};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger result = aNumber.shiftRight(number);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * testBit(int n) of a negative n
+ */
+ public void testTestBitException() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = -7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ try {
+ aNumber.testBit(number);
+ fail("ArithmeticException has not been caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * testBit(int n) of a positive number
+ */
+ public void testTestBitPositive1() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive number
+ */
+ public void testTestBitPositive2() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 45;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive number, n > bitLength()
+ */
+ public void testTestBitPositive3() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = 1;
+ int number = 300;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a negative number
+ */
+ public void testTestBitNegative1() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 7;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive n
+ */
+ public void testTestBitNegative2() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 45;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(!aNumber.testBit(number));
+ }
+
+ /**
+ * testBit(int n) of a positive n, n > bitLength()
+ */
+ public void testTestBitNegative3() {
+ byte aBytes[] = {-1, -128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26};
+ int aSign = -1;
+ int number = 300;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ assertTrue(aNumber.testBit(number));
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java
new file mode 100644
index 0000000..3509643
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerOrTest.java
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: or
+ */
+public class BigIntegerOrTest extends TestCase {
+ /**
+ * Or for zero and a positive number
+ */
+ public void testZeroPos() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for zero and a negative number
+ */
+ public void testZeroNeg() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 0;
+ int bSign = -1;
+ byte rBytes[] = {-1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a positive number and zero
+ */
+ public void testPosZero() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = 1;
+ int bSign = 0;
+ byte rBytes[] = {0, -2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for a negative number and zero
+ */
+ public void testNegPos() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {0};
+ int aSign = -1;
+ int bSign = 0;
+ byte rBytes[] = {-1, 1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for zero and zero
+ */
+ public void testZeroZero() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ byte rBytes[] = {0};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 0, result.signum());
+ }
+
+ /**
+ * Or for zero and one
+ */
+ public void testZeroOne() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {1};
+ int aSign = 0;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for one and one
+ */
+ public void testOneOne() {
+ byte aBytes[] = {1};
+ byte bBytes[] = {1};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -2, -3, -4, -4, -1, -66, 95, 47, 123, 59, -13, 39, 30, -97};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87, -17, -73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {0, -128, 9, 56, 100, -2, -3, -3, -3, 95, 15, -9, 39, 58, -69, 87, 87, -17, -73};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", 1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 127, -57, -101, -5, -5, -18, -38, -17, -2, -65, -2, -11, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 1, 75, -89, -45, -2, -3, -18, -36, -17, -10, -3, -6, -7, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 1, -126, 59, 103, -2, -11, -7, -3, -33, -57, -3, -5, -5, -21};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ byte aBytes[] = {-128, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1, 5, 79, -73, -9, -76, -3, 78, -35, -17, 119};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125, -22, -83, 30, 95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for two negative numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ byte aBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ byte bBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-74, 91, 47, -5, -13, -7, -5, -33, -49, -65, -1, -9, -3};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ /**
+ * Or for a positive and a negative number; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ byte aBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ byte bBytes[] = {-128, 9, 56, 100, -2, -76, 89, 45, 91, 3, -15, 35, 26, -117, 23, 87, -25, -75};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {-1, 127, -10, -57, -101, -1, -1, -2, -2, -91, -2, 31, -1, -11, 125, -22, -83, 30, 95};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.or(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals("incorrect sign", -1, result.signum());
+ }
+
+ public void testRegression() {
+ // Regression test for HARMONY-1996
+ BigInteger x = new BigInteger("-1023");
+ BigInteger r1 = x.and((BigInteger.ZERO.not()).shiftLeft(32));
+ BigInteger r3 = x.and((BigInteger.ZERO.not().shiftLeft(32) ).not());
+ BigInteger result = r1.or(r3);
+ assertEquals(x, result);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java
new file mode 100644
index 0000000..aaddd39
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerSubtractTest.java
@@ -0,0 +1,547 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: subtract
+ */
+public class BigIntegerSubtractTest extends TestCase {
+ /**
+ * Subtract two positive numbers of the same length.
+ * The first is greater.
+ */
+ public void testCase1() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of the same length.
+ * The second is greater.
+ */
+ public void testCase2() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is positive.
+ * The first is greater in absolute value.
+ */
+ public void testCase3() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is positive.
+ * The second is greater in absolute value.
+ */
+ public void testCase4() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {11, 22, 33, 44, 55, 66, 77, 11, 22, 33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of the same length.
+ * The first is greater in absolute value.
+ */
+ public void testCase5() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-10, -19, -28, -37, -46, -55, -64, -10, -19, -27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of the same length.
+ * The second is greater in absolute value.
+ */
+ public void testCase6() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {9, 18, 27, 36, 45, 54, 63, 9, 18, 27};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is negative.
+ * The first is greater in absolute value.
+ */
+ public void testCase7() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is negative.
+ * The second is greater in absolute value.
+ */
+ public void testCase8() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-12, -23, -34, -45, -56, -67, -78, -12, -23, -33};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of different length.
+ * The first is longer.
+ */
+ public void testCase9() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive numbers of different length.
+ * The second is longer.
+ */
+ public void testCase10() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of different length and different signs.
+ * The first is positive.
+ * The first is greater in absolute value.
+ */
+ public void testCase11() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is positive.
+ * The second is greater in absolute value.
+ */
+ public void testCase12() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = 1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 4, 15, 26, 37, 41, 52, 63, 74, 15, 26, 37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of different length and different signs.
+ * The first is negative.
+ * The first is longer.
+ */
+ public void testCase13() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two numbers of the same length and different signs.
+ * The first is negative.
+ * The second is longer.
+ */
+ public void testCase14() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = 1;
+ byte rBytes[] = {-2, -3, -4, -5, -16, -27, -38, -42, -53, -64, -75, -16, -27, -37};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+
+ /**
+ * Subtract two negative numbers of different length.
+ * The first is longer.
+ */
+ public void testCase15() {
+ byte aBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ byte bBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {-2, -3, -4, -4, 5, 14, 23, 39, 48, 57, 66, 5, 14, 23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+}
+
+ /**
+ * Subtract two negative numbers of different length.
+ * The second is longer.
+ */
+ public void testCase16() {
+ byte aBytes[] = {10, 20, 30, 40, 50, 60, 70, 10, 20, 30};
+ byte bBytes[] = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 7};
+ int aSign = -1;
+ int bSign = -1;
+ byte rBytes[] = {1, 2, 3, 3, -6, -15, -24, -40, -49, -58, -67, -6, -15, -23};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract two positive equal in absolute value numbers.
+ */
+ public void testCase17() {
+ byte aBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte bBytes[] = {-120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {0};
+ int aSign = 1;
+ int bSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract zero from a number.
+ * The number is positive.
+ */
+ public void testCase18() {
+ byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte bBytes[] = {0};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 1;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract a number from zero.
+ * The number is negative.
+ */
+ public void testCase19() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 0;
+ int bSign = -1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract zero from zero.
+ */
+ public void testCase20() {
+ byte aBytes[] = {0};
+ byte bBytes[] = {0};
+ byte rBytes[] = {0};
+ int aSign = 0;
+ int bSign = 0;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract ZERO from a number.
+ * The number is positive.
+ */
+ public void testCase21() {
+ byte aBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int aSign = 1;
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract a number from ZERO.
+ * The number is negative.
+ */
+ public void testCase22() {
+ byte bBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ byte rBytes[] = {120, 34, 78, -23, -111, 45, 127, 23, 45, -3};
+ int bSign = -1;
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(1, result.signum());
+ }
+
+ /**
+ * Subtract ZERO from ZERO.
+ */
+ public void testCase23() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ZERO;
+ BigInteger bNumber = BigInteger.ZERO;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract ONE from ONE.
+ */
+ public void testCase24() {
+ byte rBytes[] = {0};
+ BigInteger aNumber = BigInteger.ONE;
+ BigInteger bNumber = BigInteger.ONE;
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(0, result.signum());
+ }
+
+ /**
+ * Subtract two numbers so that borrow is 1.
+ */
+ public void testCase25() {
+ byte aBytes[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+ byte bBytes[] = {-128, -128, -128, -128, -128, -128, -128, -128, -128};
+ int aSign = 1;
+ int bSign = 1;
+ byte rBytes[] = {-128, 127, 127, 127, 127, 127, 127, 127, 127};
+ BigInteger aNumber = new BigInteger(aSign, aBytes);
+ BigInteger bNumber = new BigInteger(bSign, bBytes);
+ BigInteger result = aNumber.subtract(bNumber);
+ byte resBytes[] = new byte[rBytes.length];
+ resBytes = result.toByteArray();
+ for(int i = 0; i < resBytes.length; i++) {
+ assertTrue(resBytes[i] == rBytes[i]);
+ }
+ assertEquals(-1, result.signum());
+ }
+}
+
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java
new file mode 100644
index 0000000..3f20414
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerToStringTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import java.math.BigInteger;
+
+import junit.framework.TestCase;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: toString(int radix)
+ */
+public class BigIntegerToStringTest extends TestCase {
+ /**
+ * If 36 < radix < 2 it should be set to 10
+ */
+ public void testRadixOutOfRange() {
+ String value = "442429234853876401";
+ int radix = 10;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(45);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 2
+ */
+ public void testRadix2Neg() {
+ String value = "-101001100010010001001010101110000101010110001010010101010101010101010101010101010101010101010010101";
+ int radix = 2;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 2
+ */
+ public void testRadix2Pos() {
+ String value = "101000011111000000110101010101010101010001001010101010101010010101010101010000100010010";
+ int radix = 2;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 10
+ */
+ public void testRadix10Neg() {
+ String value = "-2489756308572364789878394872984";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 10
+ */
+ public void testRadix10Pos() {
+ String value = "2387627892347567398736473476";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 16
+ */
+ public void testRadix16Neg() {
+ String value = "-287628a883451b800865c67e8d7ff20";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 16
+ */
+ public void testRadix16Pos() {
+ String value = "287628a883451b800865c67e8d7ff20";
+ int radix = 16;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 24
+ */
+ public void testRadix24Neg() {
+ String value = "-287628a88gmn3451b8ijk00865c67e8d7ff20";
+ int radix = 24;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 24
+ */
+ public void testRadix24Pos() {
+ String value = "287628a883451bg80ijhk0865c67e8d7ff20";
+ int radix = 24;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test negative number of radix 24
+ */
+ public void testRadix36Neg() {
+ String value = "-uhguweut98iu4h3478tq3985pq98yeiuth33485yq4aiuhalai485yiaehasdkr8tywi5uhslei8";
+ int radix = 36;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+
+ /**
+ * test positive number of radix 24
+ */
+ public void testRadix36Pos() {
+ String value = "23895lt45y6vhgliuwhgi45y845htsuerhsi4586ysuerhtsio5y68peruhgsil4568ypeorihtse48y6";
+ int radix = 36;
+ BigInteger aNumber = new BigInteger(value, radix);
+ String result = aNumber.toString(radix);
+ assertTrue(result.equals(value));
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java
new file mode 100644
index 0000000..57ca78a
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/math/BigIntegerXorTest.java
@@ -0,0 +1,277 @@
+/*
+ * 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.
+ */
+/**
+ * @author Elena Semukhina
+ */
+
+package org.apache.harmony.tests.java.math;
+
+import junit.framework.TestCase;
+import java.math.BigInteger;
+
+/**
+ * Class: java.math.BigInteger
+ * Method: xor
+ */
+public class BigIntegerXorTest extends TestCase {
+ /**
+ * Xor for zero and a positive number
+ */
+ public void testZeroPos() {
+ String numA = "0";
+ String numB = "27384627835298756289327365";
+ String res = "27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and a negative number
+ */
+ public void testZeroNeg() {
+ String numA = "0";
+ String numB = "-27384627835298756289327365";
+ String res = "-27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive number and zero
+ */
+ public void testPosZero() {
+ String numA = "27384627835298756289327365";
+ String numB = "0";
+ String res = "27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a negative number and zero
+ */
+ public void testNegPos() {
+ String numA = "-27384627835298756289327365";
+ String numB = "0";
+ String res = "-27384627835298756289327365";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and zero
+ */
+ public void testZeroZero() {
+ String numA = "0";
+ String numB = "0";
+ String res = "0";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for zero and one
+ */
+ public void testZeroOne() {
+ String numA = "0";
+ String numB = "1";
+ String res = "1";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for one and one
+ */
+ public void testOneOne() {
+ String numA = "1";
+ String numB = "1";
+ String res = "0";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers of the same length
+ */
+ public void testPosPosSameLength() {
+ String numA = "283746278342837476784564875684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "71412358434940908477702819237626";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers; the first is longer
+ */
+ public void testPosPosFirstLonger() {
+ String numA = "2837462783428374767845648748973847593874837948575684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two positive numbers; the first is shorter
+ */
+ public void testPosPosFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers of the same length
+ */
+ public void testNegNegSameLength() {
+ String numA = "-283746278342837476784564875684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "71412358434940908477702819237626";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers; the first is longer
+ */
+ public void testNegNegFirstLonger() {
+ String numA = "-2837462783428374767845648748973847593874837948575684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers; the first is shorter
+ */
+ public void testNegNegFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "2837462783428374767845615168483972194300564226167553530";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two numbers of different signs and the same length
+ */
+ public void testPosNegSameLength() {
+ String numA = "283746278342837476784564875684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "-71412358434940908477702819237628";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two numbers of different signs and the same length
+ */
+ public void testNegPosSameLength() {
+ String numA = "-283746278342837476784564875684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "-71412358434940908477702819237628";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a negative and a positive numbers; the first is longer
+ */
+ public void testNegPosFirstLonger() {
+ String numA = "-2837462783428374767845648748973847593874837948575684767";
+ String numB = "293478573489347658763745839457637";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for two negative numbers; the first is shorter
+ */
+ public void testNegPosFirstShorter() {
+ String numA = "-293478573489347658763745839457637";
+ String numB = "2837462783428374767845648748973847593874837948575684767";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive and a negative numbers; the first is longer
+ */
+ public void testPosNegFirstLonger() {
+ String numA = "2837462783428374767845648748973847593874837948575684767";
+ String numB = "-293478573489347658763745839457637";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+
+ /**
+ * Xor for a positive and a negative number; the first is shorter
+ */
+ public void testPosNegFirstShorter() {
+ String numA = "293478573489347658763745839457637";
+ String numB = "-2837462783428374767845648748973847593874837948575684767";
+ String res = "-2837462783428374767845615168483972194300564226167553532";
+ BigInteger aNumber = new BigInteger(numA);
+ BigInteger bNumber = new BigInteger(numB);
+ BigInteger result = aNumber.xor(bNumber);
+ assertTrue(res.equals(result.toString()));
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java
new file mode 100644
index 0000000..e84b356
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Matcher2Test.java
@@ -0,0 +1,234 @@
+/* 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.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests Matcher methods
+ */
+@SuppressWarnings("nls")
+public class Matcher2Test extends TestCase {
+ public void test_toString() {
+ Pattern p = Pattern.compile("foo");
+ Matcher m = p.matcher("bar");
+ assertNotNull(m.toString());
+ }
+
+ public void testErrorConditions() throws PatternSyntaxException {
+ // Test match cursors in absence of a match
+ Pattern p = Pattern.compile("foo");
+ Matcher m = p.matcher("bar");
+ assertFalse(m.matches());
+
+ try {
+ m.start();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.end();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.group();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.start(1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.end(1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.group(1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ // regression test for HARMONY-2418
+ try {
+ m.usePattern(null);
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ // PASSED
+ }
+ }
+
+ public void testErrorConditions2() throws PatternSyntaxException {
+ // Test match cursors in absence of a match
+ Pattern p = Pattern.compile("(foo[0-9])(bar[a-z])");
+ Matcher m = p.matcher("foo1barzfoo2baryfoozbar5");
+
+ assertTrue(m.find());
+ assertEquals(0, m.start());
+ assertEquals(8, m.end());
+ assertEquals(0, m.start(1));
+ assertEquals(4, m.end(1));
+ assertEquals(4, m.start(2));
+ assertEquals(8, m.end(2));
+
+ try {
+ m.start(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.end(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.group(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.start(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.end(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.group(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ assertTrue(m.find());
+ assertEquals(8, m.start());
+ assertEquals(16, m.end());
+ assertEquals(8, m.start(1));
+ assertEquals(12, m.end(1));
+ assertEquals(12, m.start(2));
+ assertEquals(16, m.end(2));
+
+ try {
+ m.start(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.end(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.group(3);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.start(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.end(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.group(-1);
+ fail("IndexOutOfBoundsException expected");
+ } catch (IndexOutOfBoundsException e) {
+ }
+
+ assertFalse(m.find());
+
+ try {
+ m.start(3);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.end(3);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.group(3);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.start(-1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.end(-1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+
+ try {
+ m.group(-1);
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ }
+ }
+
+ /*
+ * Regression test for HARMONY-997
+ */
+ public void testReplacementBackSlash() {
+ String str = "replace me";
+ String replacedString = "me";
+ String substitutionString = "\\";
+ Pattern pat = Pattern.compile(replacedString);
+ Matcher mat = pat.matcher(str);
+ try {
+ mat.replaceAll(substitutionString);
+ fail("IndexOutOfBoundsException should be thrown");
+ } catch (IndexOutOfBoundsException e) {
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java
new file mode 100644
index 0000000..98450a4
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/MatcherTest.java
@@ -0,0 +1,770 @@
+/*
+ * 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.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("nls")
+public class MatcherTest extends TestCase {
+ String[] testPatterns = {
+ "(a|b)*abb",
+ "(1*2*3*4*)*567",
+ "(a|b|c|d)*aab",
+ "(1|2|3|4|5|6|7|8|9|0)(1|2|3|4|5|6|7|8|9|0)*",
+ "(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ)*",
+ "(a|b)*(a|b)*A(a|b)*lice.*",
+ "(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)(a|b|c|d|e|f|g|h|"
+ + "i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)*(1|2|3|4|5|6|7|8|9|0)*|while|for|struct|if|do" };
+
+ String[] groupPatterns = { "(a|b)*aabb", "((a)|b)*aabb", "((a|b)*)a(abb)",
+ "(((a)|(b))*)aabb", "(((a)|(b))*)aa(b)b", "(((a)|(b))*)a(a(b)b)" };
+
+ public MatcherTest(String name) {
+ super(name);
+ }
+
+ public void testRegionsIntInt() {
+ Pattern p = Pattern.compile("x*");
+ Matcher m = p.matcher("axxxxxa");
+ assertFalse(m.matches());
+
+ m.region(1, 6);
+ assertEquals(1, m.regionStart());
+ assertEquals(6, m.regionEnd());
+ assertTrue(m.matches());
+
+ try {
+ m.region(1, 0);
+ fail("expected an IOOBE");
+ } catch(IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.region(-1, 2);
+ fail("expected an IOOBE");
+ } catch(IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.region(10, 11);
+ fail("expected an IOOBE");
+ } catch(IndexOutOfBoundsException e) {
+ }
+
+ try {
+ m.region(1, 10);
+ fail("expected an IOOBE");
+ } catch(IndexOutOfBoundsException e) {
+ }
+ }
+
+ public void testAppendReplacement() {
+ Pattern pat = Pattern.compile("XX");
+ Matcher m = pat.matcher("Today is XX-XX-XX ...");
+ StringBuffer sb = new StringBuffer();
+
+ for (int i = 0; m.find(); i++) {
+ m.appendReplacement(sb, new Integer(i * 10 + i).toString());
+ }
+ m.appendTail(sb);
+ assertEquals("Today is 0-11-22 ...", sb.toString());
+ }
+
+ public void testAppendReplacementRef() {
+ Pattern p = Pattern.compile("xx (rur|\\$)");
+ Matcher m = p.matcher("xx $ equals to xx rur.");
+ StringBuffer sb = new StringBuffer();
+ for (int i = 1; m.find(); i *= 30) {
+ String rep = new Integer(i).toString() + " $1";
+ m.appendReplacement(sb, rep);
+ }
+ m.appendTail(sb);
+ assertEquals("1 $ equals to 30 rur.", sb.toString());
+ }
+
+ public void testReplaceAll() {
+ String input = "aabfooaabfooabfoob";
+ String pattern = "a*b";
+ Pattern pat = Pattern.compile(pattern);
+ Matcher mat = pat.matcher(input);
+
+ assertEquals("-foo-foo-foo-", mat.replaceAll("-"));
+ }
+
+ /*
+ * Class under test for Matcher reset(CharSequence)
+ */
+ public void testResetCharSequence() {
+ Pattern p = Pattern.compile("abcd");
+ Matcher m = p.matcher("abcd");
+ assertTrue(m.matches());
+ m.reset("efgh");
+ assertFalse(m.matches());
+
+ try {
+ m.reset(null);
+ fail("expected a NPE");
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void testAppendSlashes() {
+ Pattern p = Pattern.compile("\\\\");
+ Matcher m = p.matcher("one\\cat\\two\\cats\\in\\the\\yard");
+ StringBuffer sb = new StringBuffer();
+ while (m.find()) {
+ m.appendReplacement(sb, "\\\\");
+ }
+ m.appendTail(sb);
+ assertEquals("one\\cat\\two\\cats\\in\\the\\yard", sb.toString());
+
+ }
+
+ public void testReplaceFirst() {
+ String input = "zzzdogzzzdogzzz";
+ String pattern = "dog";
+ Pattern pat = Pattern.compile(pattern);
+ Matcher mat = pat.matcher(input);
+
+ assertEquals("zzzcatzzzdogzzz", mat.replaceFirst("cat"));
+ }
+
+ public void testPattern() {
+ for (String element : testPatterns) {
+ Pattern test = Pattern.compile(element);
+ assertEquals(test, test.matcher("aaa").pattern());
+ }
+
+ for (String element : testPatterns) {
+ assertEquals(element, Pattern.compile(element).matcher("aaa")
+ .pattern().toString());
+ }
+ }
+
+ /*
+ * Class under test for Matcher reset()
+ */
+ public void testReset() {
+ }
+
+ /*
+ * Class under test for String group(int)
+ */
+ public void testGroupint() {
+ String positiveTestString = "ababababbaaabb";
+
+ // test IndexOutOfBoundsException
+ // //
+ for (int i = 0; i < groupPatterns.length; i++) {
+ Pattern test = Pattern.compile(groupPatterns[i]);
+ Matcher mat = test.matcher(positiveTestString);
+ mat.matches();
+ try {
+ // groupPattern <index + 1> equals to number of groups
+ // of the specified pattern
+ // //
+ mat.group(i + 2);
+ fail("IndexOutBoundsException expected");
+ mat.group(i + 100);
+ fail("IndexOutBoundsException expected");
+ mat.group(-1);
+ fail("IndexOutBoundsException expected");
+ mat.group(-100);
+ fail("IndexOutBoundsException expected");
+ } catch (IndexOutOfBoundsException iobe) {
+ }
+ }
+
+ String[][] groupResults = { { "a" }, { "a", "a" },
+ { "ababababba", "a", "abb" }, { "ababababba", "a", "a", "b" },
+ { "ababababba", "a", "a", "b", "b" },
+ { "ababababba", "a", "a", "b", "abb", "b" }, };
+
+ for (int i = 0; i < groupPatterns.length; i++) {
+ Pattern test = Pattern.compile(groupPatterns[i]);
+ Matcher mat = test.matcher(positiveTestString);
+ mat.matches();
+ for (int j = 0; j < groupResults[i].length; j++) {
+ assertEquals("i: " + i + " j: " + j, groupResults[i][j], mat
+ .group(j + 1));
+ }
+
+ }
+
+ }
+
+ public void testGroup() {
+ String positiveTestString = "ababababbaaabb";
+ String negativeTestString = "gjhfgdsjfhgcbv";
+ for (String element : groupPatterns) {
+ Pattern test = Pattern.compile(element);
+ Matcher mat = test.matcher(positiveTestString);
+ mat.matches();
+ // test result
+ assertEquals(positiveTestString, mat.group());
+
+ // test equal to group(0) result
+ assertEquals(mat.group(0), mat.group());
+ }
+
+ for (String element : groupPatterns) {
+ Pattern test = Pattern.compile(element);
+ Matcher mat = test.matcher(negativeTestString);
+ mat.matches();
+ try {
+ mat.group();
+ fail("IllegalStateException expected for <false> matches result");
+ } catch (IllegalStateException ise) {
+ }
+ }
+ }
+
+ public void testGroupPossessive() {
+ Pattern pat = Pattern.compile("((a)|(b))++c");
+ Matcher mat = pat.matcher("aac");
+
+ mat.matches();
+ assertEquals("a", mat.group(1));
+ }
+
+ /*
+ * Class under test for boolean find(int)
+ */
+ public void testFindint() {
+ }
+
+ /*
+ * Class under test for int start(int)
+ */
+ public void testStartint() {
+ }
+
+ /*
+ * Class under test for int end(int)
+ */
+ public void testEndint() {
+ }
+
+ public void testMatchesMisc() {
+ String[][] posSeq = {
+ { "abb", "ababb", "abababbababb", "abababbababbabababbbbbabb" },
+ { "213567", "12324567", "1234567", "213213567",
+ "21312312312567", "444444567" },
+ { "abcdaab", "aab", "abaab", "cdaab", "acbdadcbaab" },
+ { "213234567", "3458", "0987654", "7689546432", "0398576",
+ "98432", "5" },
+ {
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" },
+ { "ababbaAabababblice", "ababbaAliceababab", "ababbAabliceaaa",
+ "abbbAbbbliceaaa", "Alice" },
+ { "a123", "bnxnvgds156", "for", "while", "if", "struct" }
+
+ };
+
+ for (int i = 0; i < testPatterns.length; i++) {
+ Pattern pat = Pattern.compile(testPatterns[i]);
+ for (int j = 0; j < posSeq[i].length; j++) {
+ Matcher mat = pat.matcher(posSeq[i][j]);
+ assertTrue("Incorrect match: " + testPatterns[i] + " vs "
+ + posSeq[i][j], mat.matches());
+ }
+ }
+ }
+
+ public void testMatchesQuantifiers() {
+ String[] testPatternsSingles = { "a{5}", "a{2,4}", "a{3,}" };
+ String[] testPatternsMultiple = { "((a)|(b)){1,2}abb",
+ "((a)|(b)){2,4}", "((a)|(b)){3,}" };
+
+ String[][] stringSingles = { { "aaaaa", "aaa" },
+ { "aa", "a", "aaa", "aaaaaa", "aaaa", "aaaaa" },
+ { "aaa", "a", "aaaa", "aa" }, };
+
+ String[][] stringMultiples = { { "ababb", "aba" },
+ { "ab", "b", "bab", "ababa", "abba", "abababbb" },
+ { "aba", "b", "abaa", "ba" }, };
+
+ for (int i = 0; i < testPatternsSingles.length; i++) {
+ Pattern pat = Pattern.compile(testPatternsSingles[i]);
+ for (int j = 0; j < stringSingles.length / 2; j++) {
+ assertTrue("Match expected, but failed: " + pat.pattern()
+ + " : " + stringSingles[i][j], pat.matcher(
+ stringSingles[i][j * 2]).matches());
+ assertFalse("Match failure expected, but match succeed: "
+ + pat.pattern() + " : " + stringSingles[i][j * 2 + 1],
+ pat.matcher(stringSingles[i][j * 2 + 1]).matches());
+ }
+ }
+
+ for (int i = 0; i < testPatternsMultiple.length; i++) {
+ Pattern pat = Pattern.compile(testPatternsMultiple[i]);
+ for (int j = 0; j < stringMultiples.length / 2; j++) {
+ assertTrue("Match expected, but failed: " + pat.pattern()
+ + " : " + stringMultiples[i][j], pat.matcher(
+ stringMultiples[i][j * 2]).matches());
+ assertFalse(
+ "Match failure expected, but match succeed: "
+ + pat.pattern() + " : "
+ + stringMultiples[i][j * 2 + 1], pat.matcher(
+ stringMultiples[i][j * 2 + 1]).matches());
+ }
+ }
+ }
+
+ public void testQuantVsGroup() {
+ String patternString = "(d{1,3})((a|c)*)(d{1,3})((a|c)*)(d{1,3})";
+ String testString = "dacaacaacaaddaaacaacaaddd";
+
+ Pattern pat = Pattern.compile(patternString);
+ Matcher mat = pat.matcher(testString);
+
+ mat.matches();
+ assertEquals("dacaacaacaaddaaacaacaaddd", mat.group());
+ assertEquals("d", mat.group(1));
+ assertEquals("acaacaacaa", mat.group(2));
+ assertEquals("dd", mat.group(4));
+ assertEquals("aaacaacaa", mat.group(5));
+ assertEquals("ddd", mat.group(7));
+ }
+
+ public void testLookingAt() {
+ }
+
+ /*
+ * Class under test for boolean find()
+ */
+ public void testFind() {
+ String testPattern = "(abb)";
+ String testString = "cccabbabbabbabbabb";
+ Pattern pat = Pattern.compile(testPattern);
+ Matcher mat = pat.matcher(testString);
+ int start = 3;
+ int end = 6;
+ while (mat.find()) {
+ assertEquals(start, mat.start(1));
+ assertEquals(end, mat.end(1));
+
+ start = end;
+ end += 3;
+ }
+
+ testPattern = "(\\d{1,3})";
+ testString = "aaaa123456789045";
+
+ Pattern pat2 = Pattern.compile(testPattern);
+ Matcher mat2 = pat2.matcher(testString);
+ start = 4;
+ int length = 3;
+ while (mat2.find()) {
+ assertEquals(testString.substring(start, start + length), mat2
+ .group(1));
+ start += length;
+ }
+ }
+
+ public void testSEOLsymbols() {
+ Pattern pat = Pattern.compile("^a\\(bb\\[$");
+ Matcher mat = pat.matcher("a(bb[");
+
+ assertTrue(mat.matches());
+ }
+
+ /*
+ * Class under test for int start()
+ */
+ public void testStart() {
+ }
+
+ public void testGroupCount() {
+ for (int i = 0; i < groupPatterns.length; i++) {
+ Pattern test = Pattern.compile(groupPatterns[i]);
+ Matcher mat = test.matcher("ababababbaaabb");
+ mat.matches();
+ assertEquals(i + 1, mat.groupCount());
+
+ }
+ }
+
+ public void testRelactantQuantifiers() {
+ Pattern pat = Pattern.compile("(ab*)*b");
+ Matcher mat = pat.matcher("abbbb");
+
+ if (mat.matches()) {
+ assertEquals("abbb", mat.group(1));
+ } else {
+ fail("Match expected: (ab*)*b vs abbbb");
+ }
+ }
+
+ public void testEnhancedFind() {
+ String input = "foob";
+ String pattern = "a*b";
+ Pattern pat = Pattern.compile(pattern);
+ Matcher mat = pat.matcher(input);
+
+ mat.find();
+ assertEquals("b", mat.group());
+ }
+
+ public void testPosCompositeGroup() {
+ String[] posExamples = { "aabbcc", "aacc", "bbaabbcc" };
+ String[] negExamples = { "aabb", "bb", "bbaabb" };
+ Pattern posPat = Pattern.compile("(aa|bb){1,3}+cc");
+ Pattern negPat = Pattern.compile("(aa|bb){1,3}+bb");
+
+ Matcher mat;
+ for (String element : posExamples) {
+ mat = posPat.matcher(element);
+ assertTrue(mat.matches());
+ }
+
+ for (String element : negExamples) {
+ mat = negPat.matcher(element);
+ assertFalse(mat.matches());
+ }
+
+ assertTrue(Pattern.matches("(aa|bb){1,3}+bb", "aabbaabb"));
+
+ }
+
+ public void testPosAltGroup() {
+ String[] posExamples = { "aacc", "bbcc", "cc" };
+ String[] negExamples = { "bb", "aa" };
+ Pattern posPat = Pattern.compile("(aa|bb)?+cc");
+ Pattern negPat = Pattern.compile("(aa|bb)?+bb");
+
+ Matcher mat;
+ for (String element : posExamples) {
+ mat = posPat.matcher(element);
+ assertTrue(posPat.toString() + " vs: " + element, mat.matches());
+ }
+
+ for (String element : negExamples) {
+ mat = negPat.matcher(element);
+ assertFalse(mat.matches());
+ }
+
+ assertTrue(Pattern.matches("(aa|bb)?+bb", "aabb"));
+ }
+
+ public void testRelCompGroup() {
+
+ Matcher mat;
+ Pattern pat;
+ String res = "";
+ for (int i = 0; i < 4; i++) {
+ pat = Pattern.compile("((aa|bb){" + i + ",3}?).*cc");
+ mat = pat.matcher("aaaaaacc");
+ assertTrue(pat.toString() + " vs: " + "aaaaaacc", mat.matches());
+ assertEquals(res, mat.group(1));
+ res += "aa";
+ }
+ }
+
+ public void testRelAltGroup() {
+
+ Matcher mat;
+ Pattern pat;
+
+ pat = Pattern.compile("((aa|bb)??).*cc");
+ mat = pat.matcher("aacc");
+ assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
+ assertEquals("", mat.group(1));
+
+ pat = Pattern.compile("((aa|bb)??)cc");
+ mat = pat.matcher("aacc");
+ assertTrue(pat.toString() + " vs: " + "aacc", mat.matches());
+ assertEquals("aa", mat.group(1));
+ }
+
+ public void testIgnoreCase() {
+ Pattern pat = Pattern.compile("(aa|bb)*", Pattern.CASE_INSENSITIVE);
+ Matcher mat = pat.matcher("aAbb");
+
+ assertTrue(mat.matches());
+
+ pat = Pattern.compile("(a|b|c|d|e)*", Pattern.CASE_INSENSITIVE);
+ mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
+ assertTrue(mat.matches());
+
+ pat = Pattern.compile("[a-e]*", Pattern.CASE_INSENSITIVE);
+ mat = pat.matcher("aAebbAEaEdebbedEccEdebbedEaedaebEbdCCdbBDcdcdADa");
+ assertTrue(mat.matches());
+
+ }
+
+ public void testQuoteReplacement() {
+ assertEquals("\\\\aaCC\\$1", Matcher.quoteReplacement("\\aaCC$1"));
+ }
+
+ public void testOverFlow() {
+ Pattern tp = Pattern.compile("(a*)*");
+ Matcher tm = tp.matcher("aaa");
+ assertTrue(tm.matches());
+ assertEquals("", tm.group(1));
+
+ assertTrue(Pattern.matches("(1+)\\1+", "11"));
+ assertTrue(Pattern.matches("(1+)(2*)\\2+", "11"));
+
+ Pattern pat = Pattern.compile("(1+)\\1*");
+ Matcher mat = pat.matcher("11");
+
+ assertTrue(mat.matches());
+ assertEquals("11", mat.group(1));
+
+ pat = Pattern.compile("((1+)|(2+))(\\2+)");
+ mat = pat.matcher("11");
+
+ assertTrue(mat.matches());
+ assertEquals("1", mat.group(2));
+ assertEquals("1", mat.group(1));
+ assertEquals("1", mat.group(4));
+ assertNull(mat.group(3));
+
+ }
+
+ public void testUnicode() {
+
+ assertTrue(Pattern.matches("\\x61a", "aa"));
+ assertTrue(Pattern.matches("\\u0061a", "aa"));
+ assertTrue(Pattern.matches("\\0141a", "aa"));
+ assertTrue(Pattern.matches("\\0777", "?7"));
+
+ }
+
+ public void testUnicodeCategory() {
+ assertTrue(Pattern.matches("\\p{Ll}", "k")); // Unicode lower case
+ assertTrue(Pattern.matches("\\P{Ll}", "K")); // Unicode non-lower
+ // case
+ assertTrue(Pattern.matches("\\p{Lu}", "K")); // Unicode upper case
+ assertTrue(Pattern.matches("\\P{Lu}", "k")); // Unicode non-upper
+ // case
+ // combinations
+ assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "k"));
+ assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "K"));
+ assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}]]", "K"));
+ assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Ll}]]", "k"));
+
+ // category/character combinations
+ assertFalse(Pattern.matches("[\\p{L}&&[^a-z]]", "k"));
+ assertTrue(Pattern.matches("[\\p{L}&&[^a-z]]", "K"));
+
+ assertTrue(Pattern.matches("[\\p{Lu}a-z]", "k"));
+ assertTrue(Pattern.matches("[a-z\\p{Lu}]", "k"));
+
+ assertFalse(Pattern.matches("[\\p{Lu}a-d]", "k"));
+ assertTrue(Pattern.matches("[a-d\\p{Lu}]", "K"));
+
+ // assertTrue(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^K]]]", "K"));
+ assertFalse(Pattern.matches("[\\p{L}&&[^\\p{Lu}&&[^G]]]", "K"));
+
+ }
+
+ public void testSplitEmpty() {
+
+ Pattern pat = Pattern.compile("");
+ String[] s = pat.split("", -1);
+
+ assertEquals(1, s.length);
+ assertEquals("", s[0]);
+ }
+
+ public void testFindDollar() {
+ Matcher mat = Pattern.compile("a$").matcher("a\n");
+ assertTrue(mat.find());
+ assertEquals("a", mat.group());
+ }
+
+ /*
+ * Verify if the Matcher can match the input when region is changed
+ */
+ public void testMatchesRegionChanged() {
+ // Regression for HARMONY-610
+ String input = " word ";
+ Pattern pattern = Pattern.compile("\\w+");
+ Matcher matcher = pattern.matcher(input);
+ matcher.region(1, 5);
+ assertTrue(matcher.matches());
+ }
+
+ public void testAllCodePoints_p() {
+ // Regression for HARMONY-3145
+ int[] codePoint = new int[1];
+ Pattern p = Pattern.compile("(\\p{all})+");
+ boolean res = true;
+ int cnt = 0;
+ int step = 16; // Ideally 1, but devices are still too slow.
+ for (int i = 0; i < 0x110000; i += step) {
+ codePoint[0] = i;
+ String s = new String(codePoint, 0, 1);
+ if (!s.matches(p.toString())) {
+ cnt++;
+ res = false;
+ }
+ }
+ assertTrue(res);
+ assertEquals(0, cnt);
+ }
+
+ public void testAllCodePoints_P() {
+ // Regression for HARMONY-3145
+ int[] codePoint = new int[1];
+ Pattern p = Pattern.compile("(\\P{all})+");
+ boolean res = true;
+ int cnt = 0;
+ int step = 16; // Ideally 1, but devices are still too slow.
+ for (int i = 0; i < 0x110000; i += step) {
+ codePoint[0] = i;
+ String s = new String(codePoint, 0, 1);
+ if (!s.matches(p.toString())) {
+ cnt++;
+ res = false;
+ }
+ }
+ assertFalse(res);
+ assertEquals(0x110000 / step, cnt);
+ }
+
+ /*
+ * Verify if the Matcher behaves correct when region is changed
+ */
+ public void testFindRegionChanged() {
+ // Regression for HARMONY-625
+ Pattern pattern = Pattern.compile("(?s).*");
+ Matcher matcher = pattern.matcher("abcde");
+ matcher.find();
+ assertEquals("abcde", matcher.group());
+
+ matcher = pattern.matcher("abcde");
+ matcher.region(0, 2);
+ matcher.find();
+ assertEquals("ab", matcher.group());
+
+ }
+
+ /*
+ * Verify if the Matcher behaves correct with pattern "c" when region is
+ * changed
+ */
+ public void testFindRegionChanged2() {
+ // Regression for HARMONY-713
+ Pattern pattern = Pattern.compile("c");
+
+ String inputStr = "aabb.c";
+ Matcher matcher = pattern.matcher(inputStr);
+ matcher.region(0, 3);
+
+ assertFalse(matcher.find());
+ }
+
+ /*
+ * Regression test for HARMONY-674
+ */
+ public void testPatternMatcher() throws Exception {
+ Pattern pattern = Pattern.compile("(?:\\d+)(?:pt)");
+ assertTrue(pattern.matcher("14pt").matches());
+ }
+
+ /**
+ * Inspired by HARMONY-3360
+ */
+ public void test3360() {
+ String str = "!\"#%&'(),-./";
+ Pattern p = Pattern.compile("\\s");
+ Matcher m = p.matcher(str);
+
+ assertFalse(m.find());
+ }
+
+ /**
+ * Regression test for HARMONY-3360
+ */
+ public void testGeneralPunctuationCategory() {
+ String[] s = { ",", "!", "\"", "#", "%", "&", "'", "(", ")", "-", ".",
+ "/" };
+ String regexp = "\\p{P}";
+
+ for (int i = 0; i < s.length; i++) {
+ Pattern pattern = Pattern.compile(regexp);
+ Matcher matcher = pattern.matcher(s[i]);
+ assertTrue(matcher.find());
+ }
+ }
+
+ /**
+ * Regression test for HARMONY-4396
+ */
+ public void testHitEndAfterFind() {
+ hitEndTest(true, "#01.0", "r((ege)|(geg))x", "regexx", false);
+ hitEndTest(true, "#01.1", "r((ege)|(geg))x", "regex", false);
+ hitEndTest(true, "#01.2", "r((ege)|(geg))x", "rege", true);
+ hitEndTest(true, "#01.2", "r((ege)|(geg))x", "xregexx", false);
+
+ hitEndTest(true, "#02.0", "regex", "rexreger", true);
+ hitEndTest(true, "#02.1", "regex", "raxregexr", false);
+
+ String floatRegex = getHexFloatRegex();
+ hitEndTest(true, "#03.0", floatRegex, Double.toHexString(-1.234d), true);
+ hitEndTest(true, "#03.1", floatRegex, "1 ABC"
+ + Double.toHexString(Double.NaN) + "buhuhu", false);
+ hitEndTest(true, "#03.2", floatRegex, Double.toHexString(-0.0) + "--",
+ false);
+ hitEndTest(true, "#03.3", floatRegex, "--"
+ + Double.toHexString(Double.MIN_VALUE) + "--", false);
+
+ hitEndTest(true, "#04.0", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
+ "1 fish 2 fish red fish 5", true);
+ hitEndTest(true, "#04.1", "(\\d+) fish (\\d+) fish (\\w+) fish (\\d+)",
+ "----1 fish 2 fish red fish 5----", false);
+ }
+
+ public void testToString() {
+ Matcher m = Pattern.compile("(\\d{1,3})").matcher("aaaa666456789045");
+ assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=0,16 lastmatch=]", m.toString());
+ assertTrue(m.find());
+ assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=0,16 lastmatch=666]", m.toString());
+ m.region(4, 8);
+ assertEquals("java.util.regex.Matcher[pattern=(\\d{1,3}) region=4,8 lastmatch=]", m.toString());
+ }
+
+ private void hitEndTest(boolean callFind, String testNo, String regex,
+ String input, boolean hit) {
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(input);
+ if (callFind) {
+ matcher.find();
+ } else {
+ matcher.matches();
+ }
+ boolean h = matcher.hitEnd();
+
+ assertTrue(testNo, h == hit);
+ }
+
+ private String getHexFloatRegex() {
+ String hexDecimal = "(-|\\+)?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP](-|\\+)?[0-9]+)?";
+ String notANumber = "((-|\\+)?Infinity)|([nN]a[nN])";
+ return new StringBuilder("((").append(hexDecimal).append(")|(").append(
+ notANumber).append("))").toString();
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java
new file mode 100644
index 0000000..c34cebe
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ModeTest.java
@@ -0,0 +1,111 @@
+/* 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.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests Pattern compilation modes and modes triggered in pattern strings
+ */
+@SuppressWarnings("nls")
+public class ModeTest extends TestCase {
+ public void testCase() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ p = Pattern.compile("([a-z]+)[0-9]+");
+ m = p.matcher("cAT123#dog345");
+ assertTrue(m.find());
+ assertEquals("dog", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("([a-z]+)[0-9]+", Pattern.CASE_INSENSITIVE);
+ m = p.matcher("cAt123#doG345");
+ assertTrue(m.find());
+ assertEquals("cAt", m.group(1));
+ assertTrue(m.find());
+ assertEquals("doG", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("(?i)([a-z]+)[0-9]+");
+ m = p.matcher("cAt123#doG345");
+ assertTrue(m.find());
+ assertEquals("cAt", m.group(1));
+ assertTrue(m.find());
+ assertEquals("doG", m.group(1));
+ assertFalse(m.find());
+ }
+
+ public void testMultiline() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ p = Pattern.compile("^foo");
+ m = p.matcher("foobar");
+ assertTrue(m.find());
+ assertTrue(m.start() == 0 && m.end() == 3);
+ assertFalse(m.find());
+
+ m = p.matcher("barfoo");
+ assertFalse(m.find());
+
+ p = Pattern.compile("foo$");
+ m = p.matcher("foobar");
+ assertFalse(m.find());
+
+ m = p.matcher("barfoo");
+ assertTrue(m.find());
+ assertTrue(m.start() == 3 && m.end() == 6);
+ assertFalse(m.find());
+
+ p = Pattern.compile("^foo([0-9]*)", Pattern.MULTILINE);
+ m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+ assertTrue(m.find());
+ assertEquals("1", m.group(1));
+ assertTrue(m.find());
+ assertEquals("2", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("foo([0-9]*)$", Pattern.MULTILINE);
+ m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+ assertTrue(m.find());
+ assertEquals("3", m.group(1));
+ assertTrue(m.find());
+ assertEquals("4", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("(?m)^foo([0-9]*)");
+ m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+ assertTrue(m.find());
+ assertEquals("1", m.group(1));
+ assertTrue(m.find());
+ assertEquals("2", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("(?m)foo([0-9]*)$");
+ m = p.matcher("foo1bar\nfoo2foo3\nbarfoo4");
+ assertTrue(m.find());
+ assertEquals("3", m.group(1));
+ assertTrue(m.find());
+ assertEquals("4", m.group(1));
+ assertFalse(m.find());
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java
new file mode 100644
index 0000000..cf30fc6
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/Pattern2Test.java
@@ -0,0 +1,1299 @@
+/* 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.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests simple Pattern compilation and Matcher methods
+ */
+@SuppressWarnings("nls")
+public class Pattern2Test extends TestCase {
+ public void testSimpleMatch() throws PatternSyntaxException {
+ Pattern p = Pattern.compile("foo.*");
+
+ Matcher m1 = p.matcher("foo123");
+ assertTrue(m1.matches());
+ assertTrue(m1.find(0));
+ assertTrue(m1.lookingAt());
+
+ Matcher m2 = p.matcher("fox");
+ assertFalse(m2.matches());
+ assertFalse(m2.find(0));
+ assertFalse(m2.lookingAt());
+
+ assertTrue(Pattern.matches("foo.*", "foo123"));
+ assertFalse(Pattern.matches("foo.*", "fox"));
+
+ assertFalse(Pattern.matches("bar", "foobar"));
+
+ assertTrue(Pattern.matches("", ""));
+ }
+
+ public void testCursors() {
+ Pattern p;
+ Matcher m;
+
+ try {
+ p = Pattern.compile("foo");
+
+ m = p.matcher("foobar");
+ assertTrue(m.find());
+ assertEquals(0, m.start());
+ assertEquals(3, m.end());
+ assertFalse(m.find());
+
+ // Note: also testing reset here
+ m.reset();
+ assertTrue(m.find());
+ assertEquals(0, m.start());
+ assertEquals(3, m.end());
+ assertFalse(m.find());
+
+ m.reset("barfoobar");
+ assertTrue(m.find());
+ assertEquals(3, m.start());
+ assertEquals(6, m.end());
+ assertFalse(m.find());
+
+ m.reset("barfoo");
+ assertTrue(m.find());
+ assertEquals(3, m.start());
+ assertEquals(6, m.end());
+ assertFalse(m.find());
+
+ m.reset("foobarfoobarfoo");
+ assertTrue(m.find());
+ assertEquals(0, m.start());
+ assertEquals(3, m.end());
+ assertTrue(m.find());
+ assertEquals(6, m.start());
+ assertEquals(9, m.end());
+ assertTrue(m.find());
+ assertEquals(12, m.start());
+ assertEquals(15, m.end());
+ assertFalse(m.find());
+ assertTrue(m.find(0));
+ assertEquals(0, m.start());
+ assertEquals(3, m.end());
+ assertTrue(m.find(4));
+ assertEquals(6, m.start());
+ assertEquals(9, m.end());
+ } catch (PatternSyntaxException e) {
+ System.out.println(e.getMessage());
+ fail();
+ }
+ }
+
+ public void testGroups() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ p = Pattern.compile("(p[0-9]*)#?(q[0-9]*)");
+
+ m = p.matcher("p1#q3p2q42p5p71p63#q888");
+ assertTrue(m.find());
+ assertEquals(0, m.start());
+ assertEquals(5, m.end());
+ assertEquals(2, m.groupCount());
+ assertEquals(0, m.start(0));
+ assertEquals(5, m.end(0));
+ assertEquals(0, m.start(1));
+ assertEquals(2, m.end(1));
+ assertEquals(3, m.start(2));
+ assertEquals(5, m.end(2));
+ assertEquals("p1#q3", m.group());
+ assertEquals("p1#q3", m.group(0));
+ assertEquals("p1", m.group(1));
+ assertEquals("q3", m.group(2));
+
+ assertTrue(m.find());
+ assertEquals(5, m.start());
+ assertEquals(10, m.end());
+ assertEquals(2, m.groupCount());
+ assertEquals(10, m.end(0));
+ assertEquals(5, m.start(1));
+ assertEquals(7, m.end(1));
+ assertEquals(7, m.start(2));
+ assertEquals(10, m.end(2));
+ assertEquals("p2q42", m.group());
+ assertEquals("p2q42", m.group(0));
+ assertEquals("p2", m.group(1));
+ assertEquals("q42", m.group(2));
+
+ assertTrue(m.find());
+ assertEquals(15, m.start());
+ assertEquals(23, m.end());
+ assertEquals(2, m.groupCount());
+ assertEquals(15, m.start(0));
+ assertEquals(23, m.end(0));
+ assertEquals(15, m.start(1));
+ assertEquals(18, m.end(1));
+ assertEquals(19, m.start(2));
+ assertEquals(23, m.end(2));
+ assertEquals("p63#q888", m.group());
+ assertEquals("p63#q888", m.group(0));
+ assertEquals("p63", m.group(1));
+ assertEquals("q888", m.group(2));
+ assertFalse(m.find());
+ }
+
+ public void testReplace() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ // Note: examples from book,
+ // Hitchens, Ron, 2002, "Java NIO", O'Reilly, page 171
+ p = Pattern.compile("a*b");
+
+ m = p.matcher("aabfooaabfooabfoob");
+ assertTrue(m.replaceAll("-").equals("-foo-foo-foo-"));
+ assertTrue(m.replaceFirst("-").equals("-fooaabfooabfoob"));
+
+ /*
+ * p = Pattern.compile ("\\p{Blank}");
+ *
+ * m = p.matcher ("fee fie foe fum"); assertTrue
+ * (m.replaceFirst("-").equals ("fee-fie foe fum")); assertTrue
+ * (m.replaceAll("-").equals ("fee-fie-foe-fum"));
+ */
+
+ p = Pattern.compile("([bB])yte");
+
+ m = p.matcher("Byte for byte");
+ assertTrue(m.replaceFirst("$1ite").equals("Bite for byte"));
+ assertTrue(m.replaceAll("$1ite").equals("Bite for bite"));
+
+ p = Pattern.compile("\\d\\d\\d\\d([- ])");
+
+ m = p.matcher("card #1234-5678-1234");
+ assertTrue(m.replaceFirst("xxxx$1").equals("card #xxxx-5678-1234"));
+ assertTrue(m.replaceAll("xxxx$1").equals("card #xxxx-xxxx-1234"));
+
+ p = Pattern.compile("(up|left)( *)(right|down)");
+
+ m = p.matcher("left right, up down");
+ assertTrue(m.replaceFirst("$3$2$1").equals("right left, up down"));
+ assertTrue(m.replaceAll("$3$2$1").equals("right left, down up"));
+
+ p = Pattern.compile("([CcPp][hl]e[ea]se)");
+
+ m = p.matcher("I want cheese. Please.");
+ assertTrue(m.replaceFirst("<b> $1 </b>").equals(
+ "I want <b> cheese </b>. Please."));
+ assertTrue(m.replaceAll("<b> $1 </b>").equals(
+ "I want <b> cheese </b>. <b> Please </b>."));
+ }
+
+ public void testEscapes() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ // Test \\ sequence
+ p = Pattern.compile("([a-z]+)\\\\([a-z]+);");
+ m = p.matcher("fred\\ginger;abbott\\costello;jekell\\hyde;");
+ assertTrue(m.find());
+ assertEquals("fred", m.group(1));
+ assertEquals("ginger", m.group(2));
+ assertTrue(m.find());
+ assertEquals("abbott", m.group(1));
+ assertEquals("costello", m.group(2));
+ assertTrue(m.find());
+ assertEquals("jekell", m.group(1));
+ assertEquals("hyde", m.group(2));
+ assertFalse(m.find());
+
+ // Test \n, \t, \r, \f, \e, \a sequences
+ p = Pattern.compile("([a-z]+)[\\n\\t\\r\\f\\e\\a]+([a-z]+)");
+ m = p.matcher("aa\nbb;cc\u0009\rdd;ee\u000C\u001Bff;gg\n\u0007hh");
+ assertTrue(m.find());
+ assertEquals("aa", m.group(1));
+ assertEquals("bb", m.group(2));
+ assertTrue(m.find());
+ assertEquals("cc", m.group(1));
+ assertEquals("dd", m.group(2));
+ assertTrue(m.find());
+ assertEquals("ee", m.group(1));
+ assertEquals("ff", m.group(2));
+ assertTrue(m.find());
+ assertEquals("gg", m.group(1));
+ assertEquals("hh", m.group(2));
+ assertFalse(m.find());
+
+ // Test \\u and \\x sequences
+p = Pattern.compile("([0-9]+)[\\u0020:\\x21];");
+ m = p.matcher("11:;22 ;33-;44!;");
+ assertTrue(m.find());
+ assertEquals("11", m.group(1));
+ assertTrue(m.find());
+ assertEquals("22", m.group(1));
+ assertTrue(m.find());
+ assertEquals("44", m.group(1));
+ assertFalse(m.find());
+
+ // Test invalid unicode sequences
+ try {
+ p = Pattern.compile("\\u");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\u;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\u002");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\u002;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // Test invalid hex sequences
+ try {
+ p = Pattern.compile("\\x");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\x;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // icu4c allows 1 to 6 hex digits in \x escapes.
+ p = Pattern.compile("\\xa");
+ p = Pattern.compile("\\xab");
+ p = Pattern.compile("\\xabc");
+ p = Pattern.compile("\\xabcd");
+ p = Pattern.compile("\\xabcde");
+ p = Pattern.compile("\\xabcdef");
+ // (Further digits would just be treated as characters after the escape.)
+ try {
+ p = Pattern.compile("\\xg");
+ fail();
+ } catch (PatternSyntaxException expected) {
+ }
+
+ // Test \0 (octal) sequences (1, 2 and 3 digit)
+ p = Pattern.compile("([0-9]+)[\\07\\040\\0160];");
+ m = p.matcher("11\u0007;22:;33 ;44p;");
+ assertTrue(m.find());
+ assertEquals("11", m.group(1));
+ assertTrue(m.find());
+ assertEquals("33", m.group(1));
+ assertTrue(m.find());
+ assertEquals("44", m.group(1));
+ assertFalse(m.find());
+
+ // Test invalid octal sequences
+ try {
+ p = Pattern.compile("\\08");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // originally contributed test did not check the result
+ // TODO: check what RI does here
+ // try {
+ // p = Pattern.compile("\\0477");
+ // fail("PatternSyntaxException expected");
+ // } catch (PatternSyntaxException e) {
+ // }
+
+ try {
+ p = Pattern.compile("\\0");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\0;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // Test \c (control character) sequence
+ p = Pattern.compile("([0-9]+)[\\cA\\cB\\cC\\cD];");
+ m = p.matcher("11\u0001;22:;33\u0002;44p;55\u0003;66\u0004;");
+ assertTrue(m.find());
+ assertEquals("11", m.group(1));
+ assertTrue(m.find());
+ assertEquals("33", m.group(1));
+ assertTrue(m.find());
+ assertEquals("55", m.group(1));
+ assertTrue(m.find());
+ assertEquals("66", m.group(1));
+ assertFalse(m.find());
+
+ // More thorough control escape test
+ // Ensure that each escape matches exactly the corresponding
+ // character
+ // code and no others (well, from 0-255 at least)
+ int i, j;
+ for (i = 0; i < 26; i++) {
+ p = Pattern.compile("\\c" + Character.toString((char) ('A' + i)));
+ int match_char = -1;
+ for (j = 0; j < 255; j++) {
+ m = p.matcher(Character.toString((char) j));
+ if (m.matches()) {
+ assertEquals(-1, match_char);
+ match_char = j;
+ }
+ }
+ assertTrue(match_char == i + 1);
+ }
+
+ // Test invalid control escapes
+ // icu4c 50 accepts this pattern, and treats it as a literal.
+ //try {
+ p = Pattern.compile("\\c");
+ assertTrue(p.matcher("x\\cy").find());
+ // fail(p.matcher("").toString());
+ //} catch (PatternSyntaxException e) {
+ //}
+
+ // But \cH works.
+ p = Pattern.compile("\\cH");
+ assertTrue(p.matcher("x\u0008y").find());
+ assertFalse(p.matcher("x\\cHy").find());
+
+ // originally contributed test did not check the result
+ // TODO: check what RI does here
+ // try {
+ // p = Pattern.compile("\\c;");
+ // fail("PatternSyntaxException expected");
+ // } catch (PatternSyntaxException e) {
+ // }
+ //
+ // try {
+ // p = Pattern.compile("\\ca;");
+ // fail("PatternSyntaxException expected");
+ // } catch (PatternSyntaxException e) {
+ // }
+ //
+ // try {
+ // p = Pattern.compile("\\c4;");
+ // fail("PatternSyntaxException expected");
+ // } catch (PatternSyntaxException e) {
+ // }
+ }
+
+ public void testCharacterClasses() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ // Test one character range
+ p = Pattern.compile("[p].*[l]");
+ m = p.matcher("paul");
+ assertTrue(m.matches());
+ m = p.matcher("pool");
+ assertTrue(m.matches());
+ m = p.matcher("pong");
+ assertFalse(m.matches());
+ m = p.matcher("pl");
+ assertTrue(m.matches());
+
+ // Test two character range
+ p = Pattern.compile("[pm].*[lp]");
+ m = p.matcher("prop");
+ assertTrue(m.matches());
+ m = p.matcher("mall");
+ assertTrue(m.matches());
+ m = p.matcher("pong");
+ assertFalse(m.matches());
+ m = p.matcher("pill");
+ assertTrue(m.matches());
+
+ // Test range including [ and ]
+ p = Pattern.compile("[<\\[].*[\\]>]");
+ m = p.matcher("<foo>");
+ assertTrue(m.matches());
+ m = p.matcher("[bar]");
+ assertTrue(m.matches());
+ m = p.matcher("{foobar]");
+ assertFalse(m.matches());
+ m = p.matcher("<pill]");
+ assertTrue(m.matches());
+
+ // Test range using ^
+ p = Pattern.compile("[^bc][a-z]+[tr]");
+ m = p.matcher("pat");
+ assertTrue(m.matches());
+ m = p.matcher("liar");
+ assertTrue(m.matches());
+ m = p.matcher("car");
+ assertFalse(m.matches());
+ m = p.matcher("gnat");
+ assertTrue(m.matches());
+
+ // Test character range using -
+ p = Pattern.compile("[a-z]_+[a-zA-Z]-+[0-9p-z]");
+ m = p.matcher("d__F-8");
+ assertTrue(m.matches());
+ m = p.matcher("c_a-q");
+ assertTrue(m.matches());
+ m = p.matcher("a__R-a");
+ assertFalse(m.matches());
+ m = p.matcher("r_____d-----5");
+ assertTrue(m.matches());
+
+ // Test range using unicode characters and unicode and hex escapes
+ p = Pattern.compile("[\\u1234-\\u2345]_+[a-z]-+[\u0001-\\x11]");
+ m = p.matcher("\u2000_q-\u0007");
+ assertTrue(m.matches());
+ m = p.matcher("\u1234_z-\u0001");
+ assertTrue(m.matches());
+ m = p.matcher("r_p-q");
+ assertFalse(m.matches());
+ m = p.matcher("\u2345_____d-----\n");
+ assertTrue(m.matches());
+
+ // Test ranges including the "-" character
+ // "---" collides with icu4c's "--" operator, and likely to be user error anyway.
+ if (false) {
+ p = Pattern.compile("[\\*-/]_+[---]!+[--AP]");
+ m = p.matcher("-_-!!A");
+ assertTrue(m.matches());
+ m = p.matcher("\u002b_-!!!-");
+ assertTrue(m.matches());
+ m = p.matcher("!_-!@");
+ assertFalse(m.matches());
+ m = p.matcher(",______-!!!!!!!P");
+ assertTrue(m.matches());
+ }
+
+ // Test nested ranges
+ p = Pattern.compile("[pm[t]][a-z]+[[r]lp]");
+ m = p.matcher("prop");
+ assertTrue(m.matches());
+ m = p.matcher("tsar");
+ assertTrue(m.matches());
+ m = p.matcher("pong");
+ assertFalse(m.matches());
+ m = p.matcher("moor");
+ assertTrue(m.matches());
+
+ // Test character class intersection with &&
+ // TODO: figure out what x&&y or any class with a null intersection
+ // set (like [[a-c]&&[d-f]]) might mean. It doesn't mean "match
+ // nothing" and doesn't mean "match anything" so I'm stumped.
+ p = Pattern.compile("[[a-p]&&[g-z]]+-+[[a-z]&&q]-+[x&&[a-z]]-+");
+ m = p.matcher("h--q--x--");
+ assertTrue(m.matches());
+ m = p.matcher("hog--q-x-");
+ assertTrue(m.matches());
+ m = p.matcher("ape--q-x-");
+ assertFalse(m.matches());
+ m = p.matcher("mop--q-x----");
+ assertTrue(m.matches());
+
+ // Test error cases with &&
+ // This is an RI bug that icu4c doesn't have.
+ if (false) {
+ p = Pattern.compile("[&&[xyz]]");
+ m = p.matcher("&");
+ // System.out.println(m.matches());
+ m = p.matcher("x");
+ // System.out.println(m.matches());
+ m = p.matcher("y");
+ // System.out.println(m.matches());
+ }
+ p = Pattern.compile("[[xyz]&[axy]]");
+ m = p.matcher("x");
+ // System.out.println(m.matches());
+ m = p.matcher("z");
+ // System.out.println(m.matches());
+ m = p.matcher("&");
+ // System.out.println(m.matches());
+ p = Pattern.compile("[abc[123]&&[345]def]");
+ m = p.matcher("a");
+ // System.out.println(m.matches());
+
+ // icu4c rightly considers a missing rhs to && a syntax error.
+ if (false) {
+ p = Pattern.compile("[[xyz]&&]");
+ }
+
+ p = Pattern.compile("[[abc]&]");
+
+ try {
+ p = Pattern.compile("[[abc]&&");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ p = Pattern.compile("[[abc]\\&&[xyz]]");
+
+ p = Pattern.compile("[[abc]&\\&[xyz]]");
+
+ // Test 3-way intersection
+ p = Pattern.compile("[[a-p]&&[g-z]&&[d-k]]");
+ m = p.matcher("g");
+ assertTrue(m.matches());
+ m = p.matcher("m");
+ assertFalse(m.matches());
+
+ // Test nested intersection
+ p = Pattern.compile("[[[a-p]&&[g-z]]&&[d-k]]");
+ m = p.matcher("g");
+ assertTrue(m.matches());
+ m = p.matcher("m");
+ assertFalse(m.matches());
+
+ // Test character class subtraction with && and ^
+ p = Pattern.compile("[[a-z]&&[^aeiou]][aeiou][[^xyz]&&[a-z]]");
+ m = p.matcher("pop");
+ assertTrue(m.matches());
+ m = p.matcher("tag");
+ assertTrue(m.matches());
+ m = p.matcher("eat");
+ assertFalse(m.matches());
+ m = p.matcher("tax");
+ assertFalse(m.matches());
+ m = p.matcher("zip");
+ assertTrue(m.matches());
+
+ // Test . (DOT), with and without DOTALL
+ // Note: DOT not allowed in character classes
+ p = Pattern.compile(".+/x.z");
+ m = p.matcher("!$/xyz");
+ assertTrue(m.matches());
+ m = p.matcher("%\n\r/x\nz");
+ assertFalse(m.matches());
+ p = Pattern.compile(".+/x.z", Pattern.DOTALL);
+ m = p.matcher("%\n\r/x\nz");
+ assertTrue(m.matches());
+
+ // Test \d (digit)
+ p = Pattern.compile("\\d+[a-z][\\dx]");
+ m = p.matcher("42a6");
+ assertTrue(m.matches());
+ m = p.matcher("21zx");
+ assertTrue(m.matches());
+ m = p.matcher("ab6");
+ assertFalse(m.matches());
+ m = p.matcher("56912f9");
+ assertTrue(m.matches());
+
+ // Test \D (not a digit)
+ p = Pattern.compile("\\D+[a-z]-[\\D3]");
+ m = p.matcher("za-p");
+ assertTrue(m.matches());
+ m = p.matcher("%!e-3");
+ assertTrue(m.matches());
+ m = p.matcher("9a-x");
+ assertFalse(m.matches());
+ m = p.matcher("\u1234pp\ny-3");
+ assertTrue(m.matches());
+
+ // Test \s (whitespace)
+ p = Pattern.compile("<[a-zA-Z]+\\s+[0-9]+[\\sx][^\\s]>");
+ m = p.matcher("<cat \t1\fx>");
+ assertTrue(m.matches());
+ m = p.matcher("<cat \t1\f >");
+ assertFalse(m.matches());
+ m = p
+ .matcher("xyz <foo\n\r22 5> <pp \t\n\f\r \u000b41x\u1234><pp \nx7\rc> zzz");
+ assertTrue(m.find());
+ assertTrue(m.find());
+ assertFalse(m.find());
+
+ // Test \S (not whitespace)
+ p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221>");
+ m = p.matcher("<f $0**\n** 221>");
+ assertTrue(m.matches());
+ m = p.matcher("<x 441\t221>");
+ assertTrue(m.matches());
+ m = p.matcher("<z \t9\ng 221>");
+ assertFalse(m.matches());
+ m = p.matcher("<z 60\ngg\u1234\f221>");
+ assertTrue(m.matches());
+ p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221[\\S&&[^abc]]>");
+ m = p.matcher("<f $0**\n** 221x>");
+ assertTrue(m.matches());
+ m = p.matcher("<x 441\t221z>");
+ assertTrue(m.matches());
+ m = p.matcher("<x 441\t221 >");
+ assertFalse(m.matches());
+ m = p.matcher("<x 441\t221c>");
+ assertFalse(m.matches());
+ m = p.matcher("<z \t9\ng 221x>");
+ assertFalse(m.matches());
+ m = p.matcher("<z 60\ngg\u1234\f221\u0001>");
+ assertTrue(m.matches());
+
+ // Test \w (ascii word)
+ p = Pattern.compile("<\\w+\\s[0-9]+;[^\\w]\\w+/[\\w$]+;");
+ m = p.matcher("<f1 99;!foo5/a$7;");
+ assertTrue(m.matches());
+ m = p.matcher("<f$ 99;!foo5/a$7;");
+ assertFalse(m.matches());
+ m = p
+ .matcher("<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 99;!foo5/a$7;");
+ assertTrue(m.matches());
+
+ // Test \W (not an ascii word)
+ p = Pattern.compile("<\\W\\w+\\s[0-9]+;[\\W_][^\\W]+\\s[0-9]+;");
+ m = p.matcher("<$foo3\n99;_bar\t0;");
+ assertTrue(m.matches());
+ m = p.matcher("<hh 99;_g 0;");
+ assertFalse(m.matches());
+ m = p.matcher("<*xx\t00;^zz\f11;");
+ assertTrue(m.matches());
+
+ // Test x|y pattern
+ // TODO
+ }
+
+ public void testPOSIXGroups() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ // Test POSIX groups using \p and \P (in the group and not in the group)
+ // Groups are Lower, Upper, ASCII, Alpha, Digit, XDigit, Alnum, Punct,
+ // Graph, Print, Blank, Space, Cntrl
+ // Test \p{Lower}
+ /*
+ * FIXME: Requires complex range processing p = Pattern.compile("<\\p{Lower}\\d\\P{Lower}:[\\p{Lower}Z]\\s[^\\P{Lower}]>");
+ * m = p.matcher("<a4P:g x>"); assertTrue(m.matches()); m = p.matcher("<p4%:Z\tq>");
+ * assertTrue(m.matches()); m = p.matcher("<A6#:e e>");
+ * assertFalse(m.matches());
+ */
+ p = Pattern.compile("\\p{Lower}+");
+ m = p.matcher("abcdefghijklmnopqrstuvwxyz");
+ assertTrue(m.matches());
+
+ // Invalid uses of \p{Lower}
+ try {
+ p = Pattern.compile("\\p");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{Lower");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{Lower;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // Test \p{Upper}
+ /*
+ * FIXME: Requires complex range processing p = Pattern.compile("<\\p{Upper}\\d\\P{Upper}:[\\p{Upper}z]\\s[^\\P{Upper}]>");
+ * m = p.matcher("<A4p:G X>"); assertTrue(m.matches()); m = p.matcher("<P4%:z\tQ>");
+ * assertTrue(m.matches()); m = p.matcher("<a6#:E E>");
+ * assertFalse(m.matches());
+ */
+ p = Pattern.compile("\\p{Upper}+");
+ m = p.matcher("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ assertTrue(m.matches());
+
+ // Invalid uses of \p{Upper}
+ try {
+ p = Pattern.compile("\\p{Upper");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{Upper;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // Test \p{ASCII}
+ /*
+ * FIXME: Requires complex range processing p = Pattern.compile("<\\p{ASCII}\\d\\P{ASCII}:[\\p{ASCII}\u1234]\\s[^\\P{ASCII}]>");
+ * m = p.matcher("<A4\u0080:G X>"); assertTrue(m.matches()); m =
+ * p.matcher("<P4\u00ff:\u1234\t\n>"); assertTrue(m.matches()); m =
+ * p.matcher("<\u00846#:E E>"); assertFalse(m.matches())
+ */
+ int i;
+ p = Pattern.compile("\\p{ASCII}");
+ for (i = 0; i < 0x80; i++) {
+ m = p.matcher(Character.toString((char) i));
+ assertTrue(m.matches());
+ }
+ for (; i < 0xff; i++) {
+ m = p.matcher(Character.toString((char) i));
+ assertFalse(m.matches());
+ }
+
+ // Invalid uses of \p{ASCII}
+ try {
+ p = Pattern.compile("\\p{ASCII");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ try {
+ p = Pattern.compile("\\p{ASCII;");
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ }
+
+ // Test \p{Alpha}
+ // TODO
+
+ // Test \p{Digit}
+ // TODO
+
+ // Test \p{XDigit}
+ // TODO
+
+ // Test \p{Alnum}
+ // TODO
+
+ // Test \p{Punct}
+ // TODO
+
+ // Test \p{Graph}
+ // TODO
+
+ // Test \p{Print}
+ // TODO
+
+ // Test \p{Blank}
+ // TODO
+
+ // Test \p{Space}
+ // TODO
+
+ // Test \p{Cntrl}
+ // TODO
+ }
+
+ public void testUnicodeBlocks() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+ int i, j;
+
+ // Test Unicode blocks using \p and \P
+ // FIXME:
+ // Note that LatinExtended-B and ArabicPresentations-B are unrecognized
+ // by the reference JDK.
+ for (i = 0; i < UBlocks.length; i++) {
+ /*
+ * p = Pattern.compile("\\p{"+UBlocks[i].name+"}");
+ *
+ * if (UBlocks[i].low > 0) { m =
+ * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
+ * assertFalse(m.matches()); } for (j=UBlocks[i].low; j <=
+ * UBlocks[i].high; j++) { m =
+ * p.matcher(Character.toString((char)j)); assertTrue(m.matches()); }
+ * if (UBlocks[i].high < 0xFFFF) { m =
+ * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
+ * assertFalse(m.matches()); }
+ *
+ * p = Pattern.compile("\\P{"+UBlocks[i].name+"}");
+ *
+ * if (UBlocks[i].low > 0) { m =
+ * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
+ * assertTrue(m.matches()); } for (j=UBlocks[i].low; j <
+ * UBlocks[i].high; j++) { m =
+ * p.matcher(Character.toString((char)j)); assertFalse(m.matches()); }
+ * if (UBlocks[i].high < 0xFFFF) { m =
+ * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
+ * assertTrue(m.matches()); }
+ */
+
+ p = Pattern.compile("\\p{In" + UBlocks[i].name + "}");
+
+ if (UBlocks[i].low > 0) {
+ m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
+ assertFalse(UBlocks[i].name, m.matches());
+ }
+ for (j = UBlocks[i].low; j <= UBlocks[i].high; j++) {
+ m = p.matcher(Character.toString((char) j));
+ assertTrue(UBlocks[i].name, m.matches());
+ }
+ if (UBlocks[i].high < 0xFFFF) {
+ m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
+ assertFalse(UBlocks[i].name, m.matches());
+ }
+
+ p = Pattern.compile("\\P{In" + UBlocks[i].name + "}");
+
+ if (UBlocks[i].low > 0) {
+ m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
+ assertTrue(UBlocks[i].name, m.matches());
+ }
+ for (j = UBlocks[i].low; j < UBlocks[i].high; j++) {
+ m = p.matcher(Character.toString((char) j));
+ assertFalse(UBlocks[i].name, m.matches());
+ }
+ if (UBlocks[i].high < 0xFFFF) {
+ m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
+ assertTrue(UBlocks[i].name, m.matches());
+ }
+ }
+ }
+
+ public void testMisc() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+
+ // Test (?>...)
+ // TODO
+
+ // Test (?onflags-offflags)
+ // Valid flags are i,m,d,s,u,x
+ // TODO
+
+ // Test (?onflags-offflags:...)
+ // TODO
+
+ // Test \Q, \E
+ p = Pattern.compile("[a-z]+;\\Q[a-z]+;\\Q(foo.*);\\E[0-9]+");
+ m = p.matcher("abc;[a-z]+;\\Q(foo.*);411");
+ assertTrue(m.matches());
+ m = p.matcher("abc;def;foo42;555");
+ assertFalse(m.matches());
+ m = p.matcher("abc;\\Qdef;\\Qfoo99;\\E123");
+ assertFalse(m.matches());
+
+ p = Pattern.compile("[a-z]+;(foo[0-9]-\\Q(...)\\E);[0-9]+");
+ m = p.matcher("abc;foo5-(...);123");
+ assertTrue(m.matches());
+ assertEquals("foo5-(...)", m.group(1));
+ m = p.matcher("abc;foo9-(xxx);789");
+ assertFalse(m.matches());
+
+ p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q$-\\E]+);[0-9]+");
+ m = p.matcher("abc;bar0-def$-;123");
+ assertTrue(m.matches());
+
+ // FIXME:
+ // This should work the same as the pattern above but fails with the
+ // the reference JDK
+ p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q-$\\E]+);[0-9]+");
+ m = p.matcher("abc;bar0-def$-;123");
+ // assertTrue(m.matches());
+
+ // FIXME:
+ // This should work too .. it looks as if just about anything that
+ // has more
+ // than one character between \Q and \E is broken in the the reference
+ // JDK
+ p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q[0-9]\\E]+);[0-9]+");
+ m = p.matcher("abc;bar0-def[99]-]0x[;123");
+ // assertTrue(m.matches());
+
+ // This is the same as above but with explicit escapes .. and this
+ // does work
+ // on the the reference JDK
+ p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\[0\\-9\\]]+);[0-9]+");
+ m = p.matcher("abc;bar0-def[99]-]0x[;123");
+ assertTrue(m.matches());
+
+ // Test #<comment text>
+ // TODO
+ }
+
+ public void testCompile1() throws PatternSyntaxException {
+ Pattern pattern = Pattern
+ .compile("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*");
+ String name = "iso-8859-1";
+ assertTrue(pattern.matcher(name).matches());
+ }
+
+ public void testCompile2() throws PatternSyntaxException {
+ String findString = "\\Qimport\\E";
+
+ Pattern pattern = Pattern.compile(findString, 0);
+ Matcher matcher = pattern.matcher(new String(
+ "import a.A;\n\n import b.B;\nclass C {}"));
+
+ assertTrue(matcher.find(0));
+ }
+
+ public void testCompile3() throws PatternSyntaxException {
+ Pattern p;
+ Matcher m;
+ p = Pattern.compile("a$");
+ m = p.matcher("a\n");
+ assertTrue(m.find());
+ assertEquals("a", m.group());
+ assertFalse(m.find());
+
+ p = Pattern.compile("(a$)");
+ m = p.matcher("a\n");
+ assertTrue(m.find());
+ assertEquals("a", m.group());
+ assertEquals("a", m.group(1));
+ assertFalse(m.find());
+
+ p = Pattern.compile("^.*$", Pattern.MULTILINE);
+
+ m = p.matcher("a\n");
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("a", m.group());
+ assertFalse(m.find());
+
+ m = p.matcher("a\nb\n");
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("a", m.group());
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("b", m.group());
+ assertFalse(m.find());
+
+ m = p.matcher("a\nb");
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("a", m.group());
+ assertTrue(m.find());
+ assertEquals("b", m.group());
+ assertFalse(m.find());
+
+ m = p.matcher("\naa\r\nbb\rcc\n\n");
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertTrue(m.group().equals(""));
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("aa", m.group());
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("bb", m.group());
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertEquals("cc", m.group());
+ assertTrue(m.find());
+ // System.out.println("["+m.group()+"]");
+ assertTrue(m.group().equals(""));
+ assertFalse(m.find());
+
+ m = p.matcher("a");
+ assertTrue(m.find());
+ assertEquals("a", m.group());
+ assertFalse(m.find());
+
+ m = p.matcher("");
+ // This differs from the RI behaviour but seems more correct.
+ assertTrue(m.find());
+ assertTrue(m.group().equals(""));
+ assertFalse(m.find());
+
+ p = Pattern.compile("^.*$");
+ m = p.matcher("");
+ assertTrue(m.find());
+ assertTrue(m.group().equals(""));
+ assertFalse(m.find());
+ }
+
+ public void testCompile4() throws PatternSyntaxException {
+ String findString = "\\Qpublic\\E";
+ StringBuffer text = new StringBuffer(" public class Class {\n"
+ + " public class Class {");
+
+ Pattern pattern = Pattern.compile(findString, 0);
+ Matcher matcher = pattern.matcher(text);
+
+ boolean found = matcher.find();
+ assertTrue(found);
+ assertEquals(4, matcher.start());
+ if (found) {
+ // modify text
+ text.delete(0, text.length());
+ text.append("Text have been changed.");
+ matcher.reset(text);
+ }
+
+ found = matcher.find();
+ assertFalse(found);
+ }
+
+ public void testCompile5() throws PatternSyntaxException {
+ Pattern p = Pattern.compile("^[0-9]");
+ String s[] = p.split("12", -1);
+ assertEquals("", s[0]);
+ assertEquals("2", s[1]);
+ assertEquals(2, s.length);
+ }
+
+ // public void testCompile6() {
+ // String regex = "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+";
+ // String regex = "[\\p{L}\\p{Mn}\\p{Pc}\\p{Nd}\\p{Nl}\\p{Sc}]+";
+ // try {
+ // Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
+ // assertTrue(true);
+ // } catch (PatternSyntaxException e) {
+ // System.out.println(e.getMessage());
+ // assertTrue(false);
+ // }
+ // }
+
+ private static class UBInfo {
+ public UBInfo(int low, int high, String name) {
+ this.name = name;
+ this.low = low;
+ this.high = high;
+ }
+
+ public String name;
+
+ public int low, high;
+ }
+
+ // A table representing the unicode categories
+ // private static UBInfo[] UCategories = {
+ // Lu
+ // Ll
+ // Lt
+ // Lm
+ // Lo
+ // Mn
+ // Mc
+ // Me
+ // Nd
+ // Nl
+ // No
+ // Pc
+ // Pd
+ // Ps
+ // Pe
+ // Pi
+ // Pf
+ // Po
+ // Sm
+ // Sc
+ // Sk
+ // So
+ // Zs
+ // Zl
+ // Zp
+ // Cc
+ // Cf
+ // Cs
+ // Co
+ // Cn
+ // };
+
+ // A table representing the unicode character blocks
+ private static UBInfo[] UBlocks = {
+ /* 0000; 007F; Basic Latin */
+ new UBInfo(0x0000, 0x007F, "BasicLatin"), // Character.UnicodeBlock.BASIC_LATIN
+ /* 0080; 00FF; Latin-1 Supplement */
+ new UBInfo(0x0080, 0x00FF, "Latin-1Supplement"), // Character.UnicodeBlock.LATIN_1_SUPPLEMENT
+ /* 0100; 017F; Latin Extended-A */
+ new UBInfo(0x0100, 0x017F, "LatinExtended-A"), // Character.UnicodeBlock.LATIN_EXTENDED_A
+ /* 0180; 024F; Latin Extended-B */
+ // new UBInfo (0x0180,0x024F,"InLatinExtended-B"), //
+ // Character.UnicodeBlock.LATIN_EXTENDED_B
+ /* 0250; 02AF; IPA Extensions */
+ new UBInfo(0x0250, 0x02AF, "IPAExtensions"), // Character.UnicodeBlock.IPA_EXTENSIONS
+ /* 02B0; 02FF; Spacing Modifier Letters */
+ new UBInfo(0x02B0, 0x02FF, "SpacingModifierLetters"), // Character.UnicodeBlock.SPACING_MODIFIER_LETTERS
+ /* 0300; 036F; Combining Diacritical Marks */
+ new UBInfo(0x0300, 0x036F, "CombiningDiacriticalMarks"), // Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS
+ /* 0370; 03FF; Greek */
+ new UBInfo(0x0370, 0x03FF, "Greek"), // Character.UnicodeBlock.GREEK
+ /* 0400; 04FF; Cyrillic */
+ new UBInfo(0x0400, 0x04FF, "Cyrillic"), // Character.UnicodeBlock.CYRILLIC
+ /* 0530; 058F; Armenian */
+ new UBInfo(0x0530, 0x058F, "Armenian"), // Character.UnicodeBlock.ARMENIAN
+ /* 0590; 05FF; Hebrew */
+ new UBInfo(0x0590, 0x05FF, "Hebrew"), // Character.UnicodeBlock.HEBREW
+ /* 0600; 06FF; Arabic */
+ new UBInfo(0x0600, 0x06FF, "Arabic"), // Character.UnicodeBlock.ARABIC
+ /* 0700; 074F; Syriac */
+ new UBInfo(0x0700, 0x074F, "Syriac"), // Character.UnicodeBlock.SYRIAC
+ /* 0780; 07BF; Thaana */
+ new UBInfo(0x0780, 0x07BF, "Thaana"), // Character.UnicodeBlock.THAANA
+ /* 0900; 097F; Devanagari */
+ new UBInfo(0x0900, 0x097F, "Devanagari"), // Character.UnicodeBlock.DEVANAGARI
+ /* 0980; 09FF; Bengali */
+ new UBInfo(0x0980, 0x09FF, "Bengali"), // Character.UnicodeBlock.BENGALI
+ /* 0A00; 0A7F; Gurmukhi */
+ new UBInfo(0x0A00, 0x0A7F, "Gurmukhi"), // Character.UnicodeBlock.GURMUKHI
+ /* 0A80; 0AFF; Gujarati */
+ new UBInfo(0x0A80, 0x0AFF, "Gujarati"), // Character.UnicodeBlock.GUJARATI
+ /* 0B00; 0B7F; Oriya */
+ new UBInfo(0x0B00, 0x0B7F, "Oriya"), // Character.UnicodeBlock.ORIYA
+ /* 0B80; 0BFF; Tamil */
+ new UBInfo(0x0B80, 0x0BFF, "Tamil"), // Character.UnicodeBlock.TAMIL
+ /* 0C00; 0C7F; Telugu */
+ new UBInfo(0x0C00, 0x0C7F, "Telugu"), // Character.UnicodeBlock.TELUGU
+ /* 0C80; 0CFF; Kannada */
+ new UBInfo(0x0C80, 0x0CFF, "Kannada"), // Character.UnicodeBlock.KANNADA
+ /* 0D00; 0D7F; Malayalam */
+ new UBInfo(0x0D00, 0x0D7F, "Malayalam"), // Character.UnicodeBlock.MALAYALAM
+ /* 0D80; 0DFF; Sinhala */
+ new UBInfo(0x0D80, 0x0DFF, "Sinhala"), // Character.UnicodeBlock.SINHALA
+ /* 0E00; 0E7F; Thai */
+ new UBInfo(0x0E00, 0x0E7F, "Thai"), // Character.UnicodeBlock.THAI
+ /* 0E80; 0EFF; Lao */
+ new UBInfo(0x0E80, 0x0EFF, "Lao"), // Character.UnicodeBlock.LAO
+ /* 0F00; 0FFF; Tibetan */
+ new UBInfo(0x0F00, 0x0FFF, "Tibetan"), // Character.UnicodeBlock.TIBETAN
+ /* 1000; 109F; Myanmar */
+ new UBInfo(0x1000, 0x109F, "Myanmar"), // Character.UnicodeBlock.MYANMAR
+ /* 10A0; 10FF; Georgian */
+ new UBInfo(0x10A0, 0x10FF, "Georgian"), // Character.UnicodeBlock.GEORGIAN
+ /* 1100; 11FF; Hangul Jamo */
+ new UBInfo(0x1100, 0x11FF, "HangulJamo"), // Character.UnicodeBlock.HANGUL_JAMO
+ /* 1200; 137F; Ethiopic */
+ new UBInfo(0x1200, 0x137F, "Ethiopic"), // Character.UnicodeBlock.ETHIOPIC
+ /* 13A0; 13FF; Cherokee */
+ new UBInfo(0x13A0, 0x13FF, "Cherokee"), // Character.UnicodeBlock.CHEROKEE
+ /* 1400; 167F; Unified Canadian Aboriginal Syllabics */
+ new UBInfo(0x1400, 0x167F, "UnifiedCanadianAboriginalSyllabics"), // Character.UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
+ /* 1680; 169F; Ogham */
+ new UBInfo(0x1680, 0x169F, "Ogham"), // Character.UnicodeBlock.OGHAM
+ /* 16A0; 16FF; Runic */
+ new UBInfo(0x16A0, 0x16FF, "Runic"), // Character.UnicodeBlock.RUNIC
+ /* 1780; 17FF; Khmer */
+ new UBInfo(0x1780, 0x17FF, "Khmer"), // Character.UnicodeBlock.KHMER
+ /* 1800; 18AF; Mongolian */
+ new UBInfo(0x1800, 0x18AF, "Mongolian"), // Character.UnicodeBlock.MONGOLIAN
+ /* 1E00; 1EFF; Latin Extended Additional */
+ new UBInfo(0x1E00, 0x1EFF, "LatinExtendedAdditional"), // Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL
+ /* 1F00; 1FFF; Greek Extended */
+ new UBInfo(0x1F00, 0x1FFF, "GreekExtended"), // Character.UnicodeBlock.GREEK_EXTENDED
+ /* 2000; 206F; General Punctuation */
+ new UBInfo(0x2000, 0x206F, "GeneralPunctuation"), // Character.UnicodeBlock.GENERAL_PUNCTUATION
+ /* 2070; 209F; Superscripts and Subscripts */
+ new UBInfo(0x2070, 0x209F, "SuperscriptsandSubscripts"), // Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS
+ /* 20A0; 20CF; Currency Symbols */
+ new UBInfo(0x20A0, 0x20CF, "CurrencySymbols"), // Character.UnicodeBlock.CURRENCY_SYMBOLS
+ /* 20D0; 20FF; Combining Marks for Symbols */
+ new UBInfo(0x20D0, 0x20FF, "CombiningMarksforSymbols"), // Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS
+ /* 2100; 214F; Letterlike Symbols */
+ new UBInfo(0x2100, 0x214F, "LetterlikeSymbols"), // Character.UnicodeBlock.LETTERLIKE_SYMBOLS
+ /* 2150; 218F; Number Forms */
+ new UBInfo(0x2150, 0x218F, "NumberForms"), // Character.UnicodeBlock.NUMBER_FORMS
+ /* 2190; 21FF; Arrows */
+ new UBInfo(0x2190, 0x21FF, "Arrows"), // Character.UnicodeBlock.ARROWS
+ /* 2200; 22FF; Mathematical Operators */
+ new UBInfo(0x2200, 0x22FF, "MathematicalOperators"), // Character.UnicodeBlock.MATHEMATICAL_OPERATORS
+ /* 2300; 23FF; Miscellaneous Technical */
+ new UBInfo(0x2300, 0x23FF, "MiscellaneousTechnical"), // Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL
+ /* 2400; 243F; Control Pictures */
+ new UBInfo(0x2400, 0x243F, "ControlPictures"), // Character.UnicodeBlock.CONTROL_PICTURES
+ /* 2440; 245F; Optical Character Recognition */
+ new UBInfo(0x2440, 0x245F, "OpticalCharacterRecognition"), // Character.UnicodeBlock.OPTICAL_CHARACTER_RECOGNITION
+ /* 2460; 24FF; Enclosed Alphanumerics */
+ new UBInfo(0x2460, 0x24FF, "EnclosedAlphanumerics"), // Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS
+ /* 2500; 257F; Box Drawing */
+ new UBInfo(0x2500, 0x257F, "BoxDrawing"), // Character.UnicodeBlock.BOX_DRAWING
+ /* 2580; 259F; Block Elements */
+ new UBInfo(0x2580, 0x259F, "BlockElements"), // Character.UnicodeBlock.BLOCK_ELEMENTS
+ /* 25A0; 25FF; Geometric Shapes */
+ new UBInfo(0x25A0, 0x25FF, "GeometricShapes"), // Character.UnicodeBlock.GEOMETRIC_SHAPES
+ /* 2600; 26FF; Miscellaneous Symbols */
+ new UBInfo(0x2600, 0x26FF, "MiscellaneousSymbols"), // Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS
+ /* 2700; 27BF; Dingbats */
+ new UBInfo(0x2700, 0x27BF, "Dingbats"), // Character.UnicodeBlock.DINGBATS
+ /* 2800; 28FF; Braille Patterns */
+ new UBInfo(0x2800, 0x28FF, "BraillePatterns"), // Character.UnicodeBlock.BRAILLE_PATTERNS
+ /* 2E80; 2EFF; CJK Radicals Supplement */
+ new UBInfo(0x2E80, 0x2EFF, "CJKRadicalsSupplement"), // Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT
+ /* 2F00; 2FDF; Kangxi Radicals */
+ new UBInfo(0x2F00, 0x2FDF, "KangxiRadicals"), // Character.UnicodeBlock.KANGXI_RADICALS
+ /* 2FF0; 2FFF; Ideographic Description Characters */
+ new UBInfo(0x2FF0, 0x2FFF, "IdeographicDescriptionCharacters"), // Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS
+ /* 3000; 303F; CJK Symbols and Punctuation */
+ new UBInfo(0x3000, 0x303F, "CJKSymbolsandPunctuation"), // Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
+ /* 3040; 309F; Hiragana */
+ new UBInfo(0x3040, 0x309F, "Hiragana"), // Character.UnicodeBlock.HIRAGANA
+ /* 30A0; 30FF; Katakana */
+ new UBInfo(0x30A0, 0x30FF, "Katakana"), // Character.UnicodeBlock.KATAKANA
+ /* 3100; 312F; Bopomofo */
+ new UBInfo(0x3100, 0x312F, "Bopomofo"), // Character.UnicodeBlock.BOPOMOFO
+ /* 3130; 318F; Hangul Compatibility Jamo */
+ new UBInfo(0x3130, 0x318F, "HangulCompatibilityJamo"), // Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO
+ /* 3190; 319F; Kanbun */
+ new UBInfo(0x3190, 0x319F, "Kanbun"), // Character.UnicodeBlock.KANBUN
+ /* 31A0; 31BF; Bopomofo Extended */
+ new UBInfo(0x31A0, 0x31BF, "BopomofoExtended"), // Character.UnicodeBlock.BOPOMOFO_EXTENDED
+ /* 3200; 32FF; Enclosed CJK Letters and Months */
+ new UBInfo(0x3200, 0x32FF, "EnclosedCJKLettersandMonths"), // Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS
+ /* 3300; 33FF; CJK Compatibility */
+ new UBInfo(0x3300, 0x33FF, "CJKCompatibility"), // Character.UnicodeBlock.CJK_COMPATIBILITY
+ /* 3400; 4DB5; CJK Unified Ideographs Extension A */
+ new UBInfo(0x3400, 0x4DBF, "CJKUnifiedIdeographsExtensionA"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
+ /* 4E00; 9FFF; CJK Unified Ideographs */
+ new UBInfo(0x4E00, 0x9FFF, "CJKUnifiedIdeographs"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
+ /* A000; A48F; Yi Syllables */
+ new UBInfo(0xA000, 0xA48F, "YiSyllables"), // Character.UnicodeBlock.YI_SYLLABLES
+ /* A490; A4CF; Yi Radicals */
+ new UBInfo(0xA490, 0xA4CF, "YiRadicals"), // Character.UnicodeBlock.YI_RADICALS
+ /* AC00; D7A3; Hangul Syllables */
+ new UBInfo(0xAC00, 0xD7AF, "HangulSyllables"), // Character.UnicodeBlock.HANGUL_SYLLABLES
+ /* D800; DB7F; High Surrogates */
+ /* DB80; DBFF; High Private Use Surrogates */
+ /* DC00; DFFF; Low Surrogates */
+ /* E000; F8FF; Private Use */
+ /* F900; FAFF; CJK Compatibility Ideographs */
+ new UBInfo(0xF900, 0xFAFF, "CJKCompatibilityIdeographs"), // Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
+ /* FB00; FB4F; Alphabetic Presentation Forms */
+ new UBInfo(0xFB00, 0xFB4F, "AlphabeticPresentationForms"), // Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS
+ /* FB50; FDFF; Arabic Presentation Forms-A */
+ new UBInfo(0xFB50, 0xFDFF, "ArabicPresentationForms-A"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A
+ /* FE20; FE2F; Combining Half Marks */
+ new UBInfo(0xFE20, 0xFE2F, "CombiningHalfMarks"), // Character.UnicodeBlock.COMBINING_HALF_MARKS
+ /* FE30; FE4F; CJK Compatibility Forms */
+ new UBInfo(0xFE30, 0xFE4F, "CJKCompatibilityForms"), // Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
+ /* FE50; FE6F; Small Form Variants */
+ new UBInfo(0xFE50, 0xFE6F, "SmallFormVariants"), // Character.UnicodeBlock.SMALL_FORM_VARIANTS
+ /* FE70; FEFE; Arabic Presentation Forms-B */
+ new UBInfo(0xFE70, 0xFEFF, "ArabicPresentationForms-B"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B
+ /* FF00; FFEF; Halfwidth and Fullwidth Forms */
+ new UBInfo(0xFF00, 0xFFEF, "HalfwidthandFullwidthForms"), // Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
+ /* FFF0; FFFD; Specials */
+ new UBInfo(0xFFF0, 0xFFFF, "Specials") // Character.UnicodeBlock.SPECIALS
+ };
+}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
similarity index 67%
rename from luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java
rename to harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
index fd2c3ae..4abb2a0 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternErrorTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/PatternErrorTest.java
@@ -14,15 +14,16 @@
* limitations under the License.
*/
-package org.apache.harmony.regex.tests.java.util.regex;
+package org.apache.harmony.tests.java.util.regex;
import java.util.regex.Pattern;
+
import junit.framework.TestCase;
/**
* Test boundary and error conditions in java.util.regex.Pattern
- *
*/
+@SuppressWarnings("nls")
public class PatternErrorTest extends TestCase {
public void testCompileErrors() throws Exception {
// null regex string - should get NullPointerException
@@ -32,7 +33,6 @@
} catch (NullPointerException e) {
}
-
// empty regex string - no exception should be thrown
Pattern.compile("");
@@ -46,38 +46,22 @@
flags |= Pattern.UNIX_LINES;
flags |= Pattern.CASE_INSENSITIVE;
flags |= Pattern.MULTILINE;
- // BEGIN android-changed
- // We don't support that flag.
- // flags |= Pattern.CANON_EQ;
- // END android-changed
+ flags |= Pattern.CANON_EQ;
flags |= Pattern.COMMENTS;
flags |= Pattern.DOTALL;
flags |= Pattern.UNICODE_CASE;
+ flags &= ~Pattern.CANON_EQ; // Android always throws given this flag.
Pattern.compile("foo", flags);
// add invalid flags - should get IllegalArgumentException
- /*
- * TODO: Inconsistency between the reference JDK behaviour and spec - exception is
- * not thrown
- */
- /*
- * Valid test is:
- * flags |= 0xFFFFFFFF;
- * try {
- * Pattern.compile("foo",flags);
- * } catch (IllegalArgumentException e) {
- * // This is the expected exception
- * } catch (Exception e) {
- * fail();
- * }
- */
-
- /* Workaround test is: */
- // BEGIN android-changed
- // We don't support that flag.
- flags |= ~Pattern.CANON_EQ;
- // END android-changed
- // No exception expected to match incorrect the reference behaviour
- Pattern.compile("foo", flags);
+ // regression test for HARMONY-4248
+ flags |= 0xFFFFFFFF;
+ flags &= ~Pattern.CANON_EQ; // Android always throws given this flag.
+ try {
+ Pattern.compile("foo", flags);
+ fail("Expected IllegalArgumentException to be thrown");
+ } catch (IllegalArgumentException e) {
+ // This is the expected exception
+ }
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java
new file mode 100644
index 0000000..1eac3f3
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/ReplaceTest.java
@@ -0,0 +1,90 @@
+/* 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.tests.java.util.regex;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+@SuppressWarnings("nls")
+public class ReplaceTest extends TestCase {
+
+ public void testSimpleReplace() throws PatternSyntaxException {
+ String target, pattern, repl;
+
+ target = "foobarfobarfoofo1";
+ pattern = "fo[^o]";
+ repl = "xxx";
+
+ Pattern p = Pattern.compile(pattern);
+ Matcher m = p.matcher(target);
+
+ assertEquals("foobarxxxarfoofo1", m.replaceFirst(repl));
+ assertEquals("foobarxxxarfooxxx", m.replaceAll(repl));
+ }
+
+ public void testCaptureReplace() {
+ String target, pattern, repl, s;
+ Pattern p = null;
+ Matcher m;
+
+ target = "[31]foo;bar[42];[99]xyz";
+ pattern = "\\[([0-9]+)\\]([a-z]+)";
+ repl = "$2[$1]";
+
+ p = Pattern.compile(pattern);
+ m = p.matcher(target);
+ s = m.replaceFirst(repl);
+ assertEquals("foo[31];bar[42];[99]xyz", s);
+ s = m.replaceAll(repl);
+ assertEquals("foo[31];bar[42];xyz[99]", s);
+
+ target = "[31]foo(42)bar{63}zoo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;";
+ pattern = "\\[([0-9]+)\\]([a-z]+)\\(([0-9]+)\\)([a-z]+)\\{([0-9]+)\\}([a-z]+)";
+ repl = "[$5]$6($3)$4{$1}$2";
+ p = Pattern.compile(pattern);
+ m = p.matcher(target);
+ s = m.replaceFirst(repl);
+ // System.out.println(s);
+ assertEquals(
+ "[63]zoo(42)bar{31}foo;[12]abc(34)def{56}ghi;{99}xyz[88]xyz(77)xyz;",
+ s);
+ s = m.replaceAll(repl);
+ // System.out.println(s);
+ assertEquals(
+ "[63]zoo(42)bar{31}foo;[56]ghi(34)def{12}abc;{99}xyz[88]xyz(77)xyz;",
+ s);
+ }
+
+ public void testEscapeReplace() {
+ String target, pattern, repl, s;
+
+ target = "foo'bar''foo";
+ pattern = "'";
+ repl = "\\'";
+ s = target.replaceAll(pattern, repl);
+ assertEquals("foo'bar''foo", s);
+ repl = "\\\\'";
+ s = target.replaceAll(pattern, repl);
+ assertEquals("foo\\'bar\\'\\'foo", s);
+ repl = "\\$3";
+ s = target.replaceAll(pattern, repl);
+ assertEquals("foo$3bar$3$3foo", s);
+ }
+}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java
new file mode 100644
index 0000000..5a5bc2b
--- /dev/null
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/regex/SplitTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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.tests.java.util.regex;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+import junit.framework.TestCase;
+
+/**
+ * TODO Type description
+ */
+@SuppressWarnings("nls")
+public class SplitTest extends TestCase {
+
+ public void testSimple() {
+ Pattern p = Pattern.compile("/");
+ String[] results = p.split("have/you/done/it/right");
+ String[] expected = new String[] { "have", "you", "done", "it", "right" };
+ assertEquals(expected.length, results.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(results[i], expected[i]);
+ }
+ }
+
+ public void testSplit1() throws PatternSyntaxException {
+ Pattern p = Pattern.compile(" ");
+
+ String input = "poodle zoo";
+ String tokens[];
+
+ tokens = p.split(input, 1);
+ assertEquals(1, tokens.length);
+ assertTrue(tokens[0].equals(input));
+ tokens = p.split(input, 2);
+ assertEquals(2, tokens.length);
+ assertEquals("poodle", tokens[0]);
+ assertEquals("zoo", tokens[1]);
+ tokens = p.split(input, 5);
+ assertEquals(2, tokens.length);
+ assertEquals("poodle", tokens[0]);
+ assertEquals("zoo", tokens[1]);
+ tokens = p.split(input, -2);
+ assertEquals(2, tokens.length);
+ assertEquals("poodle", tokens[0]);
+ assertEquals("zoo", tokens[1]);
+ tokens = p.split(input, 0);
+ assertEquals(2, tokens.length);
+ assertEquals("poodle", tokens[0]);
+ assertEquals("zoo", tokens[1]);
+ tokens = p.split(input);
+ assertEquals(2, tokens.length);
+ assertEquals("poodle", tokens[0]);
+ assertEquals("zoo", tokens[1]);
+
+ p = Pattern.compile("d");
+
+ tokens = p.split(input, 1);
+ assertEquals(1, tokens.length);
+ assertTrue(tokens[0].equals(input));
+ tokens = p.split(input, 2);
+ assertEquals(2, tokens.length);
+ assertEquals("poo", tokens[0]);
+ assertEquals("le zoo", tokens[1]);
+ tokens = p.split(input, 5);
+ assertEquals(2, tokens.length);
+ assertEquals("poo", tokens[0]);
+ assertEquals("le zoo", tokens[1]);
+ tokens = p.split(input, -2);
+ assertEquals(2, tokens.length);
+ assertEquals("poo", tokens[0]);
+ assertEquals("le zoo", tokens[1]);
+ tokens = p.split(input, 0);
+ assertEquals(2, tokens.length);
+ assertEquals("poo", tokens[0]);
+ assertEquals("le zoo", tokens[1]);
+ tokens = p.split(input);
+ assertEquals(2, tokens.length);
+ assertEquals("poo", tokens[0]);
+ assertEquals("le zoo", tokens[1]);
+
+ p = Pattern.compile("o");
+
+ tokens = p.split(input, 1);
+ assertEquals(1, tokens.length);
+ assertTrue(tokens[0].equals(input));
+ tokens = p.split(input, 2);
+ assertEquals(2, tokens.length);
+ assertEquals("p", tokens[0]);
+ assertEquals("odle zoo", tokens[1]);
+ tokens = p.split(input, 5);
+ assertEquals(5, tokens.length);
+ assertEquals("p", tokens[0]);
+ assertTrue(tokens[1].equals(""));
+ assertEquals("dle z", tokens[2]);
+ assertTrue(tokens[3].equals(""));
+ assertTrue(tokens[4].equals(""));
+ tokens = p.split(input, -2);
+ assertEquals(5, tokens.length);
+ assertEquals("p", tokens[0]);
+ assertTrue(tokens[1].equals(""));
+ assertEquals("dle z", tokens[2]);
+ assertTrue(tokens[3].equals(""));
+ assertTrue(tokens[4].equals(""));
+ tokens = p.split(input, 0);
+ assertEquals(3, tokens.length);
+ assertEquals("p", tokens[0]);
+ assertTrue(tokens[1].equals(""));
+ assertEquals("dle z", tokens[2]);
+ tokens = p.split(input);
+ assertEquals(3, tokens.length);
+ assertEquals("p", tokens[0]);
+ assertTrue(tokens[1].equals(""));
+ assertEquals("dle z", tokens[2]);
+ }
+
+ public void testSplit2() {
+ Pattern p = Pattern.compile("");
+ String s[];
+ s = p.split("a", -1);
+ assertEquals(3, s.length);
+ assertEquals("", s[0]);
+ assertEquals("a", s[1]);
+ assertEquals("", s[2]);
+
+ s = p.split("", -1);
+ assertEquals(1, s.length);
+ assertEquals("", s[0]);
+
+ s = p.split("abcd", -1);
+ assertEquals(6, s.length);
+ assertEquals("", s[0]);
+ assertEquals("a", s[1]);
+ assertEquals("b", s[2]);
+ assertEquals("c", s[3]);
+ assertEquals("d", s[4]);
+ assertEquals("", s[5]);
+ }
+
+ public void testSplitSupplementaryWithEmptyString() {
+
+ /*
+ * See http://www.unicode.org/reports/tr18/#Supplementary_Characters We
+ * have to treat text as code points not code units.
+ */
+ Pattern p = Pattern.compile("");
+ String s[];
+ s = p.split("a\ud869\uded6b", -1);
+ assertEquals(5, s.length);
+ assertEquals("", s[0]);
+ assertEquals("a", s[1]);
+ assertEquals("\ud869\uded6", s[2]);
+ assertEquals("b", s[3]);
+ assertEquals("", s[4]);
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java b/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java
new file mode 100644
index 0000000..4fd27bf
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/math/BigDecimalTest.java
@@ -0,0 +1,952 @@
+/*
+ * 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.math;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.MathContext;
+import java.math.RoundingMode;
+
+
+public class BigDecimalTest extends junit.framework.TestCase {
+ BigInteger value = new BigInteger("12345908");
+
+ BigInteger value2 = new BigInteger("12334560000");
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger)
+ */
+ public void test_ConstructorLjava_math_BigInteger() {
+ BigDecimal big = new BigDecimal(value);
+ assertTrue("the BigDecimal value is not initialized properly", big
+ .unscaledValue().equals(value)
+ && big.scale() == 0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.math.BigInteger, int)
+ */
+ public void test_ConstructorLjava_math_BigIntegerI() {
+ BigDecimal big = new BigDecimal(value2, 5);
+ assertTrue("the BigDecimal value is not initialized properly", big
+ .unscaledValue().equals(value2)
+ && big.scale() == 5);
+ assertTrue("the BigDecimal value is not represented properly", big
+ .toString().equals("123345.60000"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(double)
+ */
+ public void test_ConstructorD() {
+ BigDecimal big = new BigDecimal(123E04);
+ assertTrue(
+ "the BigDecimal value taking a double argument is not initialized properly",
+ big.toString().equals("1230000"));
+ big = new BigDecimal(1.2345E-12);
+ assertTrue("the double representation is not correct", big
+ .doubleValue() == 1.2345E-12);
+ big = new BigDecimal(-12345E-3);
+ assertTrue("the double representation is not correct", big
+ .doubleValue() == -12.345);
+ big = new BigDecimal(5.1234567897654321e138);
+ assertTrue("the double representation is not correct", big
+ .doubleValue() == 5.1234567897654321E138
+ && big.scale() == 0);
+ big = new BigDecimal(0.1);
+ assertTrue(
+ "the double representation of 0.1 bigDecimal is not correct",
+ big.doubleValue() == 0.1);
+ big = new BigDecimal(0.00345);
+ assertTrue(
+ "the double representation of 0.00345 bigDecimal is not correct",
+ big.doubleValue() == 0.00345);
+ // regression test for HARMONY-2429
+ big = new BigDecimal(-0.0);
+ assertTrue(
+ "the double representation of -0.0 bigDecimal is not correct",
+ big.scale() == 0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+ */
+ public void test_ConstructorLjava_lang_String() throws NumberFormatException {
+ BigDecimal big = new BigDecimal("345.23499600293850");
+ assertTrue("the BigDecimal value is not initialized properly", big
+ .toString().equals("345.23499600293850")
+ && big.scale() == 14);
+ big = new BigDecimal("-12345");
+ assertTrue("the BigDecimal value is not initialized properly", big
+ .toString().equals("-12345")
+ && big.scale() == 0);
+ big = new BigDecimal("123.");
+ assertTrue("the BigDecimal value is not initialized properly", big
+ .toString().equals("123")
+ && big.scale() == 0);
+
+ new BigDecimal("1.234E02");
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+ */
+ public void test_constructor_String_plus_exp() {
+ /*
+ * BigDecimal does not support a + sign in the exponent when converting
+ * from a String
+ */
+ new BigDecimal(+23e-0);
+ new BigDecimal(-23e+0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+ */
+ public void test_constructor_String_empty() {
+ try {
+ new BigDecimal("");
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(java.lang.String)
+ */
+ public void test_constructor_String_plus_minus_exp() {
+ try {
+ new BigDecimal("+35e+-2");
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+
+ try {
+ new BigDecimal("-35e-+2");
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#BigDecimal(char[])
+ */
+ public void test_constructor_CC_plus_minus_exp() {
+ try {
+ new BigDecimal("+35e+-2".toCharArray());
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+
+ try {
+ new BigDecimal("-35e-+2".toCharArray());
+ fail("NumberFormatException expected");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#abs()
+ */
+ public void test_abs() {
+ BigDecimal big = new BigDecimal("-1234");
+ BigDecimal bigabs = big.abs();
+ assertTrue("the absolute value of -1234 is not 1234", bigabs.toString()
+ .equals("1234"));
+ big = new BigDecimal(new BigInteger("2345"), 2);
+ bigabs = big.abs();
+ assertTrue("the absolute value of 23.45 is not 23.45", bigabs
+ .toString().equals("23.45"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#add(java.math.BigDecimal)
+ */
+ public void test_addLjava_math_BigDecimal() {
+ BigDecimal add1 = new BigDecimal("23.456");
+ BigDecimal add2 = new BigDecimal("3849.235");
+ BigDecimal sum = add1.add(add2);
+ assertTrue("the sum of 23.456 + 3849.235 is wrong", sum.unscaledValue()
+ .toString().equals("3872691")
+ && sum.scale() == 3);
+ assertTrue("the sum of 23.456 + 3849.235 is not printed correctly", sum
+ .toString().equals("3872.691"));
+ BigDecimal add3 = new BigDecimal(12.34E02D);
+ assertTrue("the sum of 23.456 + 12.34E02 is not printed correctly",
+ (add1.add(add3)).toString().equals("1257.456"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#compareTo(java.math.BigDecimal)
+ */
+ public void test_compareToLjava_math_BigDecimal() {
+ BigDecimal comp1 = new BigDecimal("1.00");
+ BigDecimal comp2 = new BigDecimal(1.000000D);
+ assertTrue("1.00 and 1.000000 should be equal",
+ comp1.compareTo(comp2) == 0);
+ BigDecimal comp3 = new BigDecimal("1.02");
+ assertTrue("1.02 should be bigger than 1.00",
+ comp3.compareTo(comp1) == 1);
+ BigDecimal comp4 = new BigDecimal(0.98D);
+ assertTrue("0.98 should be less than 1.00",
+ comp4.compareTo(comp1) == -1);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int)
+ */
+ public void test_divideLjava_math_BigDecimalI() {
+ BigDecimal divd1 = new BigDecimal(value, 2);
+ BigDecimal divd2 = new BigDecimal("2.335");
+ BigDecimal divd3 = divd1.divide(divd2, BigDecimal.ROUND_UP);
+ assertTrue("123459.08/2.335 is not correct", divd3.toString().equals(
+ "52873.27")
+ && divd3.scale() == divd1.scale());
+ assertTrue(
+ "the unscaledValue representation of 123459.08/2.335 is not correct",
+ divd3.unscaledValue().toString().equals("5287327"));
+ divd2 = new BigDecimal(123.4D);
+ divd3 = divd1.divide(divd2, BigDecimal.ROUND_DOWN);
+ assertTrue("123459.08/123.4 is not correct", divd3.toString().equals(
+ "1000.47")
+ && divd3.scale() == 2);
+ divd2 = new BigDecimal(000D);
+
+ try {
+ divd1.divide(divd2, BigDecimal.ROUND_DOWN);
+ fail("divide by zero is not caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#divide(java.math.BigDecimal, int, int)
+ */
+ public void test_divideLjava_math_BigDecimalII() {
+ BigDecimal divd1 = new BigDecimal(value2, 4);
+ BigDecimal divd2 = new BigDecimal("0.0023");
+ BigDecimal divd3 = divd1.divide(divd2, 3, BigDecimal.ROUND_HALF_UP);
+ assertTrue("1233456/0.0023 is not correct", divd3.toString().equals(
+ "536285217.391")
+ && divd3.scale() == 3);
+ divd2 = new BigDecimal(1345.5E-02D);
+ divd3 = divd1.divide(divd2, 0, BigDecimal.ROUND_DOWN);
+ assertTrue(
+ "1233456/13.455 is not correct or does not have the correct scale",
+ divd3.toString().equals("91672") && divd3.scale() == 0);
+ divd2 = new BigDecimal(0000D);
+
+ try {
+ divd1.divide(divd2, 4, BigDecimal.ROUND_DOWN);
+ fail("divide by zero is not caught");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#doubleValue()
+ */
+ public void test_doubleValue() {
+ BigDecimal bigDB = new BigDecimal(-1.234E-112);
+// Commenting out this part because it causes an endless loop (see HARMONY-319 and HARMONY-329)
+// assertTrue(
+// "the double representation of this BigDecimal is not correct",
+// bigDB.doubleValue() == -1.234E-112);
+ bigDB = new BigDecimal(5.00E-324);
+ assertTrue("the double representation of bigDecimal is not correct",
+ bigDB.doubleValue() == 5.00E-324);
+ bigDB = new BigDecimal(1.79E308);
+ assertTrue("the double representation of bigDecimal is not correct",
+ bigDB.doubleValue() == 1.79E308 && bigDB.scale() == 0);
+ bigDB = new BigDecimal(-2.33E102);
+ assertTrue(
+ "the double representation of bigDecimal -2.33E102 is not correct",
+ bigDB.doubleValue() == -2.33E102 && bigDB.scale() == 0);
+ bigDB = new BigDecimal(Double.MAX_VALUE);
+ bigDB = bigDB.add(bigDB);
+ assertTrue(
+ "a + number out of the double range should return infinity",
+ bigDB.doubleValue() == Double.POSITIVE_INFINITY);
+ bigDB = new BigDecimal(-Double.MAX_VALUE);
+ bigDB = bigDB.add(bigDB);
+ assertTrue(
+ "a - number out of the double range should return neg infinity",
+ bigDB.doubleValue() == Double.NEGATIVE_INFINITY);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#equals(java.lang.Object)
+ */
+ public void test_equalsLjava_lang_Object() {
+ BigDecimal equal1 = new BigDecimal(1.00D);
+ BigDecimal equal2 = new BigDecimal("1.0");
+ assertFalse("1.00 and 1.0 should not be equal",
+ equal1.equals(equal2));
+ equal2 = new BigDecimal(1.01D);
+ assertFalse("1.00 and 1.01 should not be equal",
+ equal1.equals(equal2));
+ equal2 = new BigDecimal("1.00");
+ assertFalse("1.00D and 1.00 should not be equal",
+ equal1.equals(equal2));
+ BigInteger val = new BigInteger("100");
+ equal1 = new BigDecimal("1.00");
+ equal2 = new BigDecimal(val, 2);
+ assertTrue("1.00(string) and 1.00(bigInteger) should be equal", equal1
+ .equals(equal2));
+ equal1 = new BigDecimal(100D);
+ equal2 = new BigDecimal("2.34576");
+ assertFalse("100D and 2.34576 should not be equal", equal1
+ .equals(equal2));
+ assertFalse("bigDecimal 100D does not equal string 23415", equal1
+ .equals("23415"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#floatValue()
+ */
+ public void test_floatValue() {
+ BigDecimal fl1 = new BigDecimal("234563782344567");
+ assertTrue("the float representation of bigDecimal 234563782344567",
+ fl1.floatValue() == 234563782344567f);
+ BigDecimal fl2 = new BigDecimal(2.345E37);
+ assertTrue("the float representation of bigDecimal 2.345E37", fl2
+ .floatValue() == 2.345E37F);
+ fl2 = new BigDecimal(-1.00E-44);
+ assertTrue("the float representation of bigDecimal -1.00E-44", fl2
+ .floatValue() == -1.00E-44F);
+ fl2 = new BigDecimal(-3E12);
+ assertTrue("the float representation of bigDecimal -3E12", fl2
+ .floatValue() == -3E12F);
+ fl2 = new BigDecimal(Double.MAX_VALUE);
+ assertTrue(
+ "A number can't be represented by float should return infinity",
+ fl2.floatValue() == Float.POSITIVE_INFINITY);
+ fl2 = new BigDecimal(-Double.MAX_VALUE);
+ assertTrue(
+ "A number can't be represented by float should return infinity",
+ fl2.floatValue() == Float.NEGATIVE_INFINITY);
+
+ }
+
+ /**
+ * @tests java.math.BigDecimal#hashCode()
+ */
+ public void test_hashCode() {
+ // anything that is equal must have the same hashCode
+ BigDecimal hash = new BigDecimal("1.00");
+ BigDecimal hash2 = new BigDecimal(1.00D);
+ assertTrue("the hashCode of 1.00 and 1.00D is equal",
+ hash.hashCode() != hash2.hashCode() && !hash.equals(hash2));
+ hash2 = new BigDecimal("1.0");
+ assertTrue("the hashCode of 1.0 and 1.00 is equal",
+ hash.hashCode() != hash2.hashCode() && !hash.equals(hash2));
+ BigInteger val = new BigInteger("100");
+ hash2 = new BigDecimal(val, 2);
+ assertTrue("hashCode of 1.00 and 1.00(bigInteger) is not equal", hash
+ .hashCode() == hash2.hashCode()
+ && hash.equals(hash2));
+ hash = new BigDecimal(value, 2);
+ hash2 = new BigDecimal("-1233456.0000");
+ assertTrue("hashCode of 123459.08 and -1233456.0000 is not equal", hash
+ .hashCode() != hash2.hashCode()
+ && !hash.equals(hash2));
+ hash2 = new BigDecimal(value.negate(), 2);
+ assertTrue("hashCode of 123459.08 and -123459.08 is not equal", hash
+ .hashCode() != hash2.hashCode()
+ && !hash.equals(hash2));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#intValue()
+ */
+ public void test_intValue() {
+ BigDecimal int1 = new BigDecimal(value, 3);
+ assertTrue("the int value of 12345.908 is not 12345",
+ int1.intValue() == 12345);
+ int1 = new BigDecimal("1.99");
+ assertTrue("the int value of 1.99 is not 1", int1.intValue() == 1);
+ int1 = new BigDecimal("23423419083091823091283933");
+ // ran JDK and found representation for the above was -249268259
+ assertTrue("the int value of 23423419083091823091283933 is wrong", int1
+ .intValue() == -249268259);
+ int1 = new BigDecimal(-1235D);
+ assertTrue("the int value of -1235 is not -1235",
+ int1.intValue() == -1235);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#longValue()
+ */
+ public void test_longValue() {
+ BigDecimal long1 = new BigDecimal(value2.negate(), 0);
+ assertTrue("the long value of 12334560000 is not 12334560000", long1
+ .longValue() == -12334560000L);
+ long1 = new BigDecimal(-1345.348E-123D);
+ assertTrue("the long value of -1345.348E-123D is not zero", long1
+ .longValue() == 0);
+ long1 = new BigDecimal("31323423423419083091823091283933");
+ // ran JDK and found representation for the above was
+ // -5251313250005125155
+ assertTrue(
+ "the long value of 31323423423419083091823091283933 is wrong",
+ long1.longValue() == -5251313250005125155L);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#max(java.math.BigDecimal)
+ */
+ public void test_maxLjava_math_BigDecimal() {
+ BigDecimal max1 = new BigDecimal(value2, 1);
+ BigDecimal max2 = new BigDecimal(value2, 4);
+ assertTrue("1233456000.0 is not greater than 1233456", max1.max(max2)
+ .equals(max1));
+ max1 = new BigDecimal(-1.224D);
+ max2 = new BigDecimal(-1.2245D);
+ assertTrue("-1.224 is not greater than -1.2245", max1.max(max2).equals(
+ max1));
+ max1 = new BigDecimal(123E18);
+ max2 = new BigDecimal(123E19);
+ assertTrue("123E19 is the not the max", max1.max(max2).equals(max2));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#min(java.math.BigDecimal)
+ */
+ public void test_minLjava_math_BigDecimal() {
+ BigDecimal min1 = new BigDecimal(-12345.4D);
+ BigDecimal min2 = new BigDecimal(-12345.39D);
+ assertTrue("-12345.39 should have been returned", min1.min(min2)
+ .equals(min1));
+ min1 = new BigDecimal(value2, 5);
+ min2 = new BigDecimal(value2, 0);
+ assertTrue("123345.6 should have been returned", min1.min(min2).equals(
+ min1));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#movePointLeft(int)
+ */
+ public void test_movePointLeftI() {
+ BigDecimal movePtLeft = new BigDecimal("123456265.34");
+ BigDecimal alreadyMoved = movePtLeft.movePointLeft(5);
+ assertTrue("move point left 5 failed", alreadyMoved.scale() == 7
+ && alreadyMoved.toString().equals("1234.5626534"));
+ movePtLeft = new BigDecimal(value2.negate(), 0);
+ alreadyMoved = movePtLeft.movePointLeft(12);
+ assertTrue("move point left 12 failed", alreadyMoved.scale() == 12
+ && alreadyMoved.toString().equals("-0.012334560000"));
+ movePtLeft = new BigDecimal(123E18);
+ alreadyMoved = movePtLeft.movePointLeft(2);
+ assertTrue("move point left 2 failed",
+ alreadyMoved.scale() == movePtLeft.scale() + 2
+ && alreadyMoved.doubleValue() == 1.23E18);
+ movePtLeft = new BigDecimal(1.123E-12);
+ alreadyMoved = movePtLeft.movePointLeft(3);
+ assertTrue("move point left 3 failed",
+ alreadyMoved.scale() == movePtLeft.scale() + 3
+ && alreadyMoved.doubleValue() == 1.123E-15);
+ movePtLeft = new BigDecimal(value, 2);
+ alreadyMoved = movePtLeft.movePointLeft(-2);
+ assertTrue("move point left -2 failed",
+ alreadyMoved.scale() == movePtLeft.scale() - 2
+ && alreadyMoved.toString().equals("12345908"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#movePointRight(int)
+ */
+ public void test_movePointRightI() {
+ BigDecimal movePtRight = new BigDecimal("-1.58796521458");
+ BigDecimal alreadyMoved = movePtRight.movePointRight(8);
+ assertTrue("move point right 8 failed", alreadyMoved.scale() == 3
+ && alreadyMoved.toString().equals("-158796521.458"));
+ movePtRight = new BigDecimal(value, 2);
+ alreadyMoved = movePtRight.movePointRight(4);
+ assertTrue("move point right 4 failed", alreadyMoved.scale() == 0
+ && alreadyMoved.toString().equals("1234590800"));
+ movePtRight = new BigDecimal(134E12);
+ alreadyMoved = movePtRight.movePointRight(2);
+ assertTrue("move point right 2 failed", alreadyMoved.scale() == 0
+ && alreadyMoved.toString().equals("13400000000000000"));
+ movePtRight = new BigDecimal(-3.4E-10);
+ alreadyMoved = movePtRight.movePointRight(5);
+ assertTrue("move point right 5 failed",
+ alreadyMoved.scale() == movePtRight.scale() - 5
+ && alreadyMoved.doubleValue() == -0.000034);
+ alreadyMoved = alreadyMoved.movePointRight(-5);
+ assertTrue("move point right -5 failed", alreadyMoved
+ .equals(movePtRight));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#multiply(java.math.BigDecimal)
+ */
+ public void test_multiplyLjava_math_BigDecimal() {
+ BigDecimal multi1 = new BigDecimal(value, 5);
+ BigDecimal multi2 = new BigDecimal(2.345D);
+ BigDecimal result = multi1.multiply(multi2);
+ assertTrue("123.45908 * 2.345 is not correct: " + result, result
+ .toString().startsWith("289.51154260")
+ && result.scale() == multi1.scale() + multi2.scale());
+ multi1 = new BigDecimal("34656");
+ multi2 = new BigDecimal("-2");
+ result = multi1.multiply(multi2);
+ assertTrue("34656 * 2 is not correct", result.toString().equals(
+ "-69312")
+ && result.scale() == 0);
+ multi1 = new BigDecimal(-2.345E-02);
+ multi2 = new BigDecimal(-134E130);
+ result = multi1.multiply(multi2);
+ assertTrue("-2.345E-02 * -134E130 is not correct " + result.doubleValue(),
+ result.doubleValue() == 3.1422999999999997E130
+ && result.scale() == multi1.scale() + multi2.scale());
+ multi1 = new BigDecimal("11235");
+ multi2 = new BigDecimal("0");
+ result = multi1.multiply(multi2);
+ assertTrue("11235 * 0 is not correct", result.doubleValue() == 0
+ && result.scale() == 0);
+ multi1 = new BigDecimal("-0.00234");
+ multi2 = new BigDecimal(13.4E10);
+ result = multi1.multiply(multi2);
+ assertTrue("-0.00234 * 13.4E10 is not correct",
+ result.doubleValue() == -313560000
+ && result.scale() == multi1.scale() + multi2.scale());
+ }
+
+ /**
+ * @tests java.math.BigDecimal#negate()
+ */
+ public void test_negate() {
+ BigDecimal negate1 = new BigDecimal(value2, 7);
+ assertTrue("the negate of 1233.4560000 is not -1233.4560000", negate1
+ .negate().toString().equals("-1233.4560000"));
+ negate1 = new BigDecimal("-23465839");
+ assertTrue("the negate of -23465839 is not 23465839", negate1.negate()
+ .toString().equals("23465839"));
+ negate1 = new BigDecimal(-3.456E6);
+ assertTrue("the negate of -3.456E6 is not 3.456E6", negate1.negate()
+ .negate().equals(negate1));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#scale()
+ */
+ public void test_scale() {
+ BigDecimal scale1 = new BigDecimal(value2, 8);
+ assertTrue("the scale of the number 123.34560000 is wrong", scale1
+ .scale() == 8);
+ BigDecimal scale2 = new BigDecimal("29389.");
+ assertTrue("the scale of the number 29389. is wrong",
+ scale2.scale() == 0);
+ BigDecimal scale3 = new BigDecimal(3.374E13);
+ assertTrue("the scale of the number 3.374E13 is wrong",
+ scale3.scale() == 0);
+ BigDecimal scale4 = new BigDecimal("-3.45E-203");
+ // note the scale is calculated as 15 digits of 345000.... + exponent -
+ // 1. -1 for the 3
+ assertTrue("the scale of the number -3.45E-203 is wrong: "
+ + scale4.scale(), scale4.scale() == 205);
+ scale4 = new BigDecimal("-345.4E-200");
+ assertTrue("the scale of the number -345.4E-200 is wrong", scale4
+ .scale() == 201);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#setScale(int)
+ */
+ public void test_setScaleI() {
+ // rounding mode defaults to zero
+ BigDecimal setScale1 = new BigDecimal(value, 3);
+ BigDecimal setScale2 = setScale1.setScale(5);
+ BigInteger setresult = new BigInteger("1234590800");
+ assertTrue("the number 12345.908 after setting scale is wrong",
+ setScale2.unscaledValue().equals(setresult)
+ && setScale2.scale() == 5);
+
+ try {
+ setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UNNECESSARY);
+ fail("arithmetic Exception not caught as a result of loosing precision");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#setScale(int, int)
+ */
+ public void test_setScaleII() {
+ BigDecimal setScale1 = new BigDecimal(2.323E102);
+ BigDecimal setScale2 = setScale1.setScale(4);
+ assertTrue("the number 2.323E102 after setting scale is wrong",
+ setScale2.scale() == 4);
+ assertTrue("the representation of the number 2.323E102 is wrong",
+ setScale2.doubleValue() == 2.323E102);
+ setScale1 = new BigDecimal("-1.253E-12");
+ setScale2 = setScale1.setScale(17, BigDecimal.ROUND_CEILING);
+ assertTrue("the number -1.253E-12 after setting scale is wrong",
+ setScale2.scale() == 17);
+ assertTrue(
+ "the representation of the number -1.253E-12 after setting scale is wrong, " + setScale2.toString(),
+ setScale2.toString().equals("-1.25300E-12"));
+
+ // testing rounding Mode ROUND_CEILING
+ setScale1 = new BigDecimal(value, 4);
+ setScale2 = setScale1.setScale(1, BigDecimal.ROUND_CEILING);
+ assertTrue(
+ "the number 1234.5908 after setting scale to 1/ROUND_CEILING is wrong",
+ setScale2.toString().equals("1234.6") && setScale2.scale() == 1);
+ BigDecimal setNeg = new BigDecimal(value.negate(), 4);
+ setScale2 = setNeg.setScale(1, BigDecimal.ROUND_CEILING);
+ assertTrue(
+ "the number -1234.5908 after setting scale to 1/ROUND_CEILING is wrong",
+ setScale2.toString().equals("-1234.5")
+ && setScale2.scale() == 1);
+
+ // testing rounding Mode ROUND_DOWN
+ setScale2 = setNeg.setScale(1, BigDecimal.ROUND_DOWN);
+ assertTrue(
+ "the number -1234.5908 after setting scale to 1/ROUND_DOWN is wrong",
+ setScale2.toString().equals("-1234.5")
+ && setScale2.scale() == 1);
+ setScale1 = new BigDecimal(value, 4);
+ setScale2 = setScale1.setScale(1, BigDecimal.ROUND_DOWN);
+ assertTrue(
+ "the number 1234.5908 after setting scale to 1/ROUND_DOWN is wrong",
+ setScale2.toString().equals("1234.5") && setScale2.scale() == 1);
+
+ // testing rounding Mode ROUND_FLOOR
+ setScale2 = setScale1.setScale(1, BigDecimal.ROUND_FLOOR);
+ assertTrue(
+ "the number 1234.5908 after setting scale to 1/ROUND_FLOOR is wrong",
+ setScale2.toString().equals("1234.5") && setScale2.scale() == 1);
+ setScale2 = setNeg.setScale(1, BigDecimal.ROUND_FLOOR);
+ assertTrue(
+ "the number -1234.5908 after setting scale to 1/ROUND_FLOOR is wrong",
+ setScale2.toString().equals("-1234.6")
+ && setScale2.scale() == 1);
+
+ // testing rounding Mode ROUND_HALF_DOWN
+ setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_DOWN);
+ assertTrue(
+ "the number 1234.5908 after setting scale to 3/ROUND_HALF_DOWN is wrong",
+ setScale2.toString().equals("1234.591")
+ && setScale2.scale() == 3);
+ setScale1 = new BigDecimal(new BigInteger("12345000"), 5);
+ setScale2 = setScale1.setScale(1, BigDecimal.ROUND_HALF_DOWN);
+ assertTrue(
+ "the number 123.45908 after setting scale to 1/ROUND_HALF_DOWN is wrong",
+ setScale2.toString().equals("123.4") && setScale2.scale() == 1);
+ setScale2 = new BigDecimal("-1234.5000").setScale(0,
+ BigDecimal.ROUND_HALF_DOWN);
+ assertTrue(
+ "the number -1234.5908 after setting scale to 0/ROUND_HALF_DOWN is wrong",
+ setScale2.toString().equals("-1234") && setScale2.scale() == 0);
+
+ // testing rounding Mode ROUND_HALF_EVEN
+ setScale1 = new BigDecimal(1.2345789D);
+ setScale2 = setScale1.setScale(4, BigDecimal.ROUND_HALF_EVEN);
+ assertTrue(
+ "the number 1.2345789 after setting scale to 4/ROUND_HALF_EVEN is wrong",
+ setScale2.doubleValue() == 1.2346D && setScale2.scale() == 4);
+ setNeg = new BigDecimal(-1.2335789D);
+ setScale2 = setNeg.setScale(2, BigDecimal.ROUND_HALF_EVEN);
+ assertTrue(
+ "the number -1.2335789 after setting scale to 2/ROUND_HALF_EVEN is wrong",
+ setScale2.doubleValue() == -1.23D && setScale2.scale() == 2);
+ setScale2 = new BigDecimal("1.2345000").setScale(3,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertTrue(
+ "the number 1.2345789 after setting scale to 3/ROUND_HALF_EVEN is wrong",
+ setScale2.doubleValue() == 1.234D && setScale2.scale() == 3);
+ setScale2 = new BigDecimal("-1.2345000").setScale(3,
+ BigDecimal.ROUND_HALF_EVEN);
+ assertTrue(
+ "the number -1.2335789 after setting scale to 3/ROUND_HALF_EVEN is wrong",
+ setScale2.doubleValue() == -1.234D && setScale2.scale() == 3);
+
+ // testing rounding Mode ROUND_HALF_UP
+ setScale1 = new BigDecimal("134567.34650");
+ setScale2 = setScale1.setScale(3, BigDecimal.ROUND_HALF_UP);
+ assertTrue(
+ "the number 134567.34658 after setting scale to 3/ROUND_HALF_UP is wrong",
+ setScale2.toString().equals("134567.347")
+ && setScale2.scale() == 3);
+ setNeg = new BigDecimal("-1234.4567");
+ setScale2 = setNeg.setScale(0, BigDecimal.ROUND_HALF_UP);
+ assertTrue(
+ "the number -1234.4567 after setting scale to 0/ROUND_HALF_UP is wrong",
+ setScale2.toString().equals("-1234") && setScale2.scale() == 0);
+
+ // testing rounding Mode ROUND_UNNECESSARY
+ try {
+ setScale1.setScale(3, BigDecimal.ROUND_UNNECESSARY);
+ fail("arithmetic Exception not caught for round unnecessary");
+ } catch (ArithmeticException e) {
+ }
+
+ // testing rounding Mode ROUND_UP
+ setScale1 = new BigDecimal("100000.374");
+ setScale2 = setScale1.setScale(2, BigDecimal.ROUND_UP);
+ assertTrue(
+ "the number 100000.374 after setting scale to 2/ROUND_UP is wrong",
+ setScale2.toString().equals("100000.38")
+ && setScale2.scale() == 2);
+ setNeg = new BigDecimal(-134.34589D);
+ setScale2 = setNeg.setScale(2, BigDecimal.ROUND_UP);
+ assertTrue(
+ "the number -134.34589 after setting scale to 2/ROUND_UP is wrong",
+ setScale2.doubleValue() == -134.35D && setScale2.scale() == 2);
+
+ // testing invalid rounding modes
+ try {
+ setScale2 = setScale1.setScale(0, -123);
+ fail("IllegalArgumentException is not caught for wrong rounding mode");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigDecimal#signum()
+ */
+ public void test_signum() {
+ BigDecimal sign = new BigDecimal(123E-104);
+ assertTrue("123E-104 is not positive in signum()", sign.signum() == 1);
+ sign = new BigDecimal("-1234.3959");
+ assertTrue("-1234.3959 is not negative in signum()",
+ sign.signum() == -1);
+ sign = new BigDecimal(000D);
+ assertTrue("000D is not zero in signum()", sign.signum() == 0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#subtract(java.math.BigDecimal)
+ */
+ public void test_subtractLjava_math_BigDecimal() {
+ BigDecimal sub1 = new BigDecimal("13948");
+ BigDecimal sub2 = new BigDecimal("2839.489");
+ BigDecimal result = sub1.subtract(sub2);
+ assertTrue("13948 - 2839.489 is wrong: " + result, result.toString()
+ .equals("11108.511")
+ && result.scale() == 3);
+ BigDecimal result2 = sub2.subtract(sub1);
+ assertTrue("2839.489 - 13948 is wrong", result2.toString().equals(
+ "-11108.511")
+ && result2.scale() == 3);
+ assertTrue("13948 - 2839.489 is not the negative of 2839.489 - 13948",
+ result.equals(result2.negate()));
+ sub1 = new BigDecimal(value, 1);
+ sub2 = new BigDecimal("0");
+ result = sub1.subtract(sub2);
+ assertTrue("1234590.8 - 0 is wrong", result.equals(sub1));
+ sub1 = new BigDecimal(1.234E-03);
+ sub2 = new BigDecimal(3.423E-10);
+ result = sub1.subtract(sub2);
+ assertTrue("1.234E-03 - 3.423E-10 is wrong, " + result.doubleValue(),
+ result.doubleValue() == 0.0012339996577);
+ sub1 = new BigDecimal(1234.0123);
+ sub2 = new BigDecimal(1234.0123000);
+ result = sub1.subtract(sub2);
+ assertTrue("1234.0123 - 1234.0123000 is wrong, " + result.doubleValue(),
+ result.doubleValue() == 0.0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#toBigInteger()
+ */
+ public void test_toBigInteger() {
+ BigDecimal sub1 = new BigDecimal("-29830.989");
+ BigInteger result = sub1.toBigInteger();
+
+ assertTrue("the bigInteger equivalent of -29830.989 is wrong", result
+ .toString().equals("-29830"));
+ sub1 = new BigDecimal(-2837E10);
+ result = sub1.toBigInteger();
+ assertTrue("the bigInteger equivalent of -2837E10 is wrong", result
+ .doubleValue() == -2837E10);
+ sub1 = new BigDecimal(2.349E-10);
+ result = sub1.toBigInteger();
+ assertTrue("the bigInteger equivalent of 2.349E-10 is wrong", result
+ .equals(BigInteger.ZERO));
+ sub1 = new BigDecimal(value2, 6);
+ result = sub1.toBigInteger();
+ assertTrue("the bigInteger equivalent of 12334.560000 is wrong", result
+ .toString().equals("12334"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#toString()
+ */
+ public void test_toString() {
+ BigDecimal toString1 = new BigDecimal("1234.000");
+ assertTrue("the toString representation of 1234.000 is wrong",
+ toString1.toString().equals("1234.000"));
+ toString1 = new BigDecimal("-123.4E-5");
+ assertTrue("the toString representation of -123.4E-5 is wrong: "
+ + toString1, toString1.toString().equals("-0.001234"));
+ toString1 = new BigDecimal("-1.455E-20");
+ assertTrue("the toString representation of -1.455E-20 is wrong",
+ toString1.toString().equals("-1.455E-20"));
+ toString1 = new BigDecimal(value2, 4);
+ assertTrue("the toString representation of 1233456.0000 is wrong",
+ toString1.toString().equals("1233456.0000"));
+ }
+
+ /**
+ * @tests java.math.BigDecimal#unscaledValue()
+ */
+ public void test_unscaledValue() {
+ BigDecimal unsVal = new BigDecimal("-2839485.000");
+ assertTrue("the unscaledValue of -2839485.000 is wrong", unsVal
+ .unscaledValue().toString().equals("-2839485000"));
+ unsVal = new BigDecimal(123E10);
+ assertTrue("the unscaledValue of 123E10 is wrong", unsVal
+ .unscaledValue().toString().equals("1230000000000"));
+ unsVal = new BigDecimal("-4.56E-13");
+ assertTrue("the unscaledValue of -4.56E-13 is wrong: "
+ + unsVal.unscaledValue(), unsVal.unscaledValue().toString()
+ .equals("-456"));
+ unsVal = new BigDecimal(value, 3);
+ assertTrue("the unscaledValue of 12345.908 is wrong", unsVal
+ .unscaledValue().toString().equals("12345908"));
+
+ }
+
+ /**
+ * @tests java.math.BigDecimal#valueOf(long)
+ */
+ public void test_valueOfJ() {
+ BigDecimal valueOfL = BigDecimal.valueOf(9223372036854775806L);
+ assertTrue("the bigDecimal equivalent of 9223372036854775806 is wrong",
+ valueOfL.unscaledValue().toString().equals(
+ "9223372036854775806")
+ && valueOfL.scale() == 0);
+ assertTrue(
+ "the toString representation of 9223372036854775806 is wrong",
+ valueOfL.toString().equals("9223372036854775806"));
+ valueOfL = BigDecimal.valueOf(0L);
+ assertTrue("the bigDecimal equivalent of 0 is wrong", valueOfL
+ .unscaledValue().toString().equals("0")
+ && valueOfL.scale() == 0);
+ }
+
+ /**
+ * @tests java.math.BigDecimal#valueOf(long, int)
+ */
+ public void test_valueOfJI() {
+ BigDecimal valueOfJI = BigDecimal.valueOf(9223372036854775806L, 5);
+ assertTrue(
+ "the bigDecimal equivalent of 92233720368547.75806 is wrong",
+ valueOfJI.unscaledValue().toString().equals(
+ "9223372036854775806")
+ && valueOfJI.scale() == 5);
+ assertTrue(
+ "the toString representation of 9223372036854775806 is wrong",
+ valueOfJI.toString().equals("92233720368547.75806"));
+ valueOfJI = BigDecimal.valueOf(1234L, 8);
+ assertTrue(
+ "the bigDecimal equivalent of 92233720368547.75806 is wrong",
+ valueOfJI.unscaledValue().toString().equals("1234")
+ && valueOfJI.scale() == 8);
+ assertTrue(
+ "the toString representation of 9223372036854775806 is wrong",
+ valueOfJI.toString().equals("0.00001234"));
+ valueOfJI = BigDecimal.valueOf(0, 3);
+ assertTrue(
+ "the bigDecimal equivalent of 92233720368547.75806 is wrong",
+ valueOfJI.unscaledValue().toString().equals("0")
+ && valueOfJI.scale() == 3);
+ assertTrue(
+ "the toString representation of 9223372036854775806 is wrong",
+ valueOfJI.toString().equals("0.000"));
+
+ }
+
+ public void test_BigDecimal_serialization() throws Exception {
+ // Regression for HARMONY-1896
+ char[] in = { '1', '5', '6', '7', '8', '7', '.', '0', '0' };
+ BigDecimal bd = new BigDecimal(in, 0, 9);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(bd);
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bis);
+ BigDecimal nbd = (BigDecimal) ois.readObject();
+
+ assertEquals(bd.intValue(), nbd.intValue());
+ assertEquals(bd.doubleValue(), nbd.doubleValue(), 0.0);
+ assertEquals(bd.toString(), nbd.toString());
+ }
+
+ /**
+ * @tests java.math.BigDecimal#stripTrailingZero(long)
+ */
+ public void test_stripTrailingZero() {
+ BigDecimal sixhundredtest = new BigDecimal("600.0");
+ assertTrue("stripTrailingZero failed for 600.0",
+ ((sixhundredtest.stripTrailingZeros()).scale() == -2)
+ );
+
+ /* Single digit, no trailing zero, odd number */
+ BigDecimal notrailingzerotest = new BigDecimal("1");
+ assertTrue("stripTrailingZero failed for 1",
+ ((notrailingzerotest.stripTrailingZeros()).scale() == 0)
+ );
+
+ // BEGIN android-changed: preserve RI compatibility, so BigDecimal.equals (which checks
+ // value *and* scale) continues to work. https://issues.apache.org/jira/browse/HARMONY-4623
+ /* Zero */
+ BigDecimal zerotest = new BigDecimal("0.0000");
+ assertEquals("stripTrailingZero failed for 0.0000", 4, zerotest.stripTrailingZeros().scale());
+ }
+
+ public void testMathContextConstruction() {
+ String a = "-12380945E+61";
+ BigDecimal aNumber = new BigDecimal(a);
+ int precision = 6;
+ RoundingMode rm = RoundingMode.HALF_DOWN;
+ MathContext mcIntRm = new MathContext(precision, rm);
+ MathContext mcStr = new MathContext("precision=6 roundingMode=HALF_DOWN");
+ MathContext mcInt = new MathContext(precision);
+ BigDecimal res = aNumber.abs(mcInt);
+ assertEquals("MathContext Constructer with int precision failed",
+ res,
+ new BigDecimal("1.23809E+68"));
+
+ assertEquals("Equal MathContexts are not Equal ",
+ mcIntRm,
+ mcStr);
+
+ assertEquals("Different MathContext are reported as Equal ",
+ mcInt.equals(mcStr),
+ false);
+
+ assertEquals("Equal MathContexts have different hashcodes ",
+ mcIntRm.hashCode(),
+ mcStr.hashCode());
+
+ assertEquals("MathContext.toString() returning incorrect value",
+ mcIntRm.toString(),
+ "precision=6 roundingMode=HALF_DOWN");
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java b/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java
new file mode 100644
index 0000000..28995cb
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/math/BigIntegerTest.java
@@ -0,0 +1,988 @@
+/*
+ * 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.math;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class BigIntegerTest extends junit.framework.TestCase {
+
+ BigInteger minusTwo = new BigInteger("-2", 10);
+
+ BigInteger minusOne = new BigInteger("-1", 10);
+
+ BigInteger zero = new BigInteger("0", 10);
+
+ BigInteger one = new BigInteger("1", 10);
+
+ BigInteger two = new BigInteger("2", 10);
+
+ BigInteger ten = new BigInteger("10", 10);
+
+ BigInteger sixteen = new BigInteger("16", 10);
+
+ BigInteger oneThousand = new BigInteger("1000", 10);
+
+ BigInteger aZillion = new BigInteger(
+ "100000000000000000000000000000000000000000000000000", 10);
+
+ BigInteger twoToTheTen = new BigInteger("1024", 10);
+
+ BigInteger twoToTheSeventy = two.pow(70);
+
+ Random rand = new Random();
+
+ BigInteger bi;
+
+ BigInteger bi1;
+
+ BigInteger bi2;
+
+ BigInteger bi3;
+
+ BigInteger bi11;
+
+ BigInteger bi22;
+
+ BigInteger bi33;
+
+ BigInteger bi12;
+
+ BigInteger bi23;
+
+ BigInteger bi13;
+
+ BigInteger largePos;
+
+ BigInteger smallPos;
+
+ BigInteger largeNeg;
+
+ BigInteger smallNeg;
+
+ BigInteger[][] booleanPairs;
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(int, java.util.Random)
+ */
+ public void test_ConstructorILjava_util_Random() {
+ // regression test for HARMONY-1047
+ try {
+ new BigInteger(Integer.MAX_VALUE, (Random)null);
+ fail("NegativeArraySizeException expected");
+ } catch (NegativeArraySizeException e) {
+ // PASSED
+ }
+
+ bi = new BigInteger(70, rand);
+ bi2 = new BigInteger(70, rand);
+ assertTrue("Random number is negative", bi.compareTo(zero) >= 0);
+ assertTrue("Random number is too big",
+ bi.compareTo(twoToTheSeventy) < 0);
+ assertTrue(
+ "Two random numbers in a row are the same (might not be a bug but it very likely is)",
+ !bi.equals(bi2));
+ assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
+ }
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(byte[])
+ */
+ public void test_Constructor$B() {
+ byte[] myByteArray;
+ myByteArray = new byte[] { (byte) 0x00, (byte) 0xFF, (byte) 0xFE };
+ bi = new BigInteger(myByteArray);
+ assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
+ .setBit(16).subtract(two)));
+ myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
+ bi = new BigInteger(myByteArray);
+ assertTrue("Incorrect value for neg number", bi.equals(minusTwo));
+ }
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(int, byte[])
+ */
+ public void test_ConstructorI$B() {
+ byte[] myByteArray;
+ myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
+ bi = new BigInteger(1, myByteArray);
+ assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
+ .setBit(16).subtract(two)));
+ bi = new BigInteger(-1, myByteArray);
+ assertTrue("Incorrect value for neg number", bi.equals(BigInteger.ZERO
+ .setBit(16).subtract(two).negate()));
+ myByteArray = new byte[] { (byte) 0, (byte) 0 };
+ bi = new BigInteger(0, myByteArray);
+ assertTrue("Incorrect value for zero", bi.equals(zero));
+ myByteArray = new byte[] { (byte) 1 };
+ try {
+ new BigInteger(0, myByteArray);
+ fail("Failed to throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ // correct
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(java.lang.String)
+ */
+ public void test_constructor_String_empty() {
+ try {
+ new BigInteger("");
+ fail("Expected NumberFormatException for new BigInteger(\"\")");
+ } catch (NumberFormatException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#toByteArray()
+ */
+ public void test_toByteArray() {
+ byte[] myByteArray, anotherByteArray;
+ myByteArray = new byte[] { 97, 33, 120, 124, 50, 2, 0, 0, 0, 12, 124,
+ 42 };
+ anotherByteArray = new BigInteger(myByteArray).toByteArray();
+ assertTrue("Incorrect byte array returned",
+ myByteArray.length == anotherByteArray.length);
+ for (int counter = myByteArray.length - 1; counter >= 0; counter--) {
+ assertTrue("Incorrect values in returned byte array",
+ myByteArray[counter] == anotherByteArray[counter]);
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#isProbablePrime(int)
+ */
+ public void test_isProbablePrimeI() {
+ int fails = 0;
+ bi = new BigInteger(20, 20, rand);
+ if (!bi.isProbablePrime(17)) {
+ fails++;
+ }
+ bi = new BigInteger("4", 10);
+ if (bi.isProbablePrime(17)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ bi = BigInteger.valueOf(17L * 13L);
+ if (bi.isProbablePrime(17)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ for (long a = 2; a < 1000; a++) {
+ if (isPrime(a)) {
+ assertTrue("false negative on prime number <1000", BigInteger
+ .valueOf(a).isProbablePrime(5));
+ } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + a);
+ fails++;
+ }
+ }
+ for (int a = 0; a < 1000; a++) {
+ bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
+ BigInteger.valueOf(rand.nextInt(1000000)));
+ if (bi.isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + bi);
+ fails++;
+ }
+ }
+ for (int a = 0; a < 200; a++) {
+ bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
+ if (bi.isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + bi);
+ fails++;
+ }
+ }
+ assertTrue("Too many false positives - may indicate a problem",
+ fails <= 1);
+ }
+
+ /**
+ * @tests java.math.BigInteger#equals(java.lang.Object)
+ */
+ public void test_equalsLjava_lang_Object() {
+ assertTrue("0=0", zero.equals(BigInteger.valueOf(0)));
+ assertTrue("-123=-123", BigInteger.valueOf(-123).equals(
+ BigInteger.valueOf(-123)));
+ assertTrue("0=1", !zero.equals(one));
+ assertTrue("0=-1", !zero.equals(minusOne));
+ assertTrue("1=-1", !one.equals(minusOne));
+ assertTrue("bi3=bi3", bi3.equals(bi3));
+ assertTrue("bi3=copy of bi3", bi3.equals(bi3.negate().negate()));
+ assertTrue("bi3=bi2", !bi3.equals(bi2));
+ }
+
+ /**
+ * @tests java.math.BigInteger#compareTo(java.math.BigInteger)
+ */
+ public void test_compareToLjava_math_BigInteger() {
+ assertTrue("Smaller number returned >= 0", one.compareTo(two) < 0);
+ assertTrue("Larger number returned >= 0", two.compareTo(one) > 0);
+ assertTrue("Equal numbers did not return 0", one.compareTo(one) == 0);
+ assertTrue("Neg number messed things up",
+ two.negate().compareTo(one) < 0);
+ }
+
+ /**
+ * @tests java.math.BigInteger#intValue()
+ */
+ public void test_intValue() {
+ assertTrue("Incorrect intValue for 2**70",
+ twoToTheSeventy.intValue() == 0);
+ assertTrue("Incorrect intValue for 2", two.intValue() == 2);
+ }
+
+ /**
+ * @tests java.math.BigInteger#longValue()
+ */
+ public void test_longValue() {
+ assertTrue("Incorrect longValue for 2**70",
+ twoToTheSeventy.longValue() == 0);
+ assertTrue("Incorrect longValue for 2", two.longValue() == 2);
+ }
+
+ /**
+ * @tests java.math.BigInteger#valueOf(long)
+ */
+ public void test_valueOfJ() {
+ assertTrue("Incurred number returned for 2", BigInteger.valueOf(2L)
+ .equals(two));
+ assertTrue("Incurred number returned for 200", BigInteger.valueOf(200L)
+ .equals(BigInteger.valueOf(139).add(BigInteger.valueOf(61))));
+ }
+
+ /**
+ * @tests java.math.BigInteger#add(java.math.BigInteger)
+ */
+ public void test_addLjava_math_BigInteger() {
+ assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
+ .add(aZillion.negate()).equals(aZillion));
+ assertTrue("0+0", zero.add(zero).equals(zero));
+ assertTrue("0+1", zero.add(one).equals(one));
+ assertTrue("1+0", one.add(zero).equals(one));
+ assertTrue("1+1", one.add(one).equals(two));
+ assertTrue("0+(-1)", zero.add(minusOne).equals(minusOne));
+ assertTrue("(-1)+0", minusOne.add(zero).equals(minusOne));
+ assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(minusTwo));
+ assertTrue("1+(-1)", one.add(minusOne).equals(zero));
+ assertTrue("(-1)+1", minusOne.add(one).equals(zero));
+
+ for (int i = 0; i < 200; i++) {
+ BigInteger midbit = zero.setBit(i);
+ assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
+ .equals(zero.setBit(i + 1)));
+ }
+ BigInteger bi2p3 = bi2.add(bi3);
+ BigInteger bi3p2 = bi3.add(bi2);
+ assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
+
+ // add large positive + small positive
+
+ // add large positive + small negative
+
+ // add large negative + small positive
+
+ // add large negative + small negative
+ }
+
+ /**
+ * @tests java.math.BigInteger#negate()
+ */
+ public void test_negate() {
+ assertTrue("Single negation of zero did not result in zero", zero
+ .negate().equals(zero));
+ assertTrue("Single negation resulted in original nonzero number",
+ !aZillion.negate().equals(aZillion));
+ assertTrue("Double negation did not result in original number",
+ aZillion.negate().negate().equals(aZillion));
+
+ assertTrue("0.neg", zero.negate().equals(zero));
+ assertTrue("1.neg", one.negate().equals(minusOne));
+ assertTrue("2.neg", two.negate().equals(minusTwo));
+ assertTrue("-1.neg", minusOne.negate().equals(one));
+ assertTrue("-2.neg", minusTwo.negate().equals(two));
+ assertTrue("0x62EB40FEF85AA9EBL*2.neg", BigInteger.valueOf(
+ 0x62EB40FEF85AA9EBL * 2).negate().equals(
+ BigInteger.valueOf(-0x62EB40FEF85AA9EBL * 2)));
+ for (int i = 0; i < 200; i++) {
+ BigInteger midbit = zero.setBit(i);
+ BigInteger negate = midbit.negate();
+ assertTrue("negate negate", negate.negate().equals(midbit));
+ assertTrue("neg fails on bit " + i, midbit.negate().add(midbit)
+ .equals(zero));
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#signum()
+ */
+ public void test_signum() {
+ assertTrue("Wrong positive signum", two.signum() == 1);
+ assertTrue("Wrong zero signum", zero.signum() == 0);
+ assertTrue("Wrong neg zero signum", zero.negate().signum() == 0);
+ assertTrue("Wrong neg signum", two.negate().signum() == -1);
+ }
+
+ /**
+ * @tests java.math.BigInteger#abs()
+ */
+ public void test_abs() {
+ assertTrue("Invalid number returned for zillion", aZillion.negate()
+ .abs().equals(aZillion.abs()));
+ assertTrue("Invalid number returned for zero neg", zero.negate().abs()
+ .equals(zero));
+ assertTrue("Invalid number returned for zero", zero.abs().equals(zero));
+ assertTrue("Invalid number returned for two", two.negate().abs()
+ .equals(two));
+ }
+
+ /**
+ * @tests java.math.BigInteger#pow(int)
+ */
+ public void test_powI() {
+ assertTrue("Incorrect exponent returned for 2**10", two.pow(10).equals(
+ twoToTheTen));
+ assertTrue("Incorrect exponent returned for 2**70", two.pow(30)
+ .multiply(two.pow(40)).equals(twoToTheSeventy));
+ assertTrue("Incorrect exponent returned for 10**50", ten.pow(50)
+ .equals(aZillion));
+ }
+
+ /**
+ * @tests java.math.BigInteger#modInverse(java.math.BigInteger)
+ */
+ public void test_modInverseLjava_math_BigInteger() {
+ BigInteger a = zero, mod, inv;
+ for (int j = 3; j < 50; j++) {
+ mod = BigInteger.valueOf(j);
+ for (int i = -j + 1; i < j; i++) {
+ try {
+ a = BigInteger.valueOf(i);
+ inv = a.modInverse(mod);
+ assertTrue("bad inverse: " + a + " inv mod " + mod
+ + " equals " + inv, one.equals(a.multiply(inv).mod(
+ mod)));
+ assertTrue("inverse greater than modulo: " + a
+ + " inv mod " + mod + " equals " + inv, inv
+ .compareTo(mod) < 0);
+ assertTrue("inverse less than zero: " + a + " inv mod "
+ + mod + " equals " + inv, inv
+ .compareTo(BigInteger.ZERO) >= 0);
+ } catch (ArithmeticException e) {
+ assertTrue("should have found inverse for " + a + " mod "
+ + mod, !one.equals(a.gcd(mod)));
+ }
+ }
+ }
+ for (int j = 1; j < 10; j++) {
+ mod = bi2.add(BigInteger.valueOf(j));
+ for (int i = 0; i < 20; i++) {
+ try {
+ a = bi3.add(BigInteger.valueOf(i));
+ inv = a.modInverse(mod);
+ assertTrue("bad inverse: " + a + " inv mod " + mod
+ + " equals " + inv, one.equals(a.multiply(inv).mod(
+ mod)));
+ assertTrue("inverse greater than modulo: " + a
+ + " inv mod " + mod + " equals " + inv, inv
+ .compareTo(mod) < 0);
+ assertTrue("inverse less than zero: " + a + " inv mod "
+ + mod + " equals " + inv, inv
+ .compareTo(BigInteger.ZERO) >= 0);
+ } catch (ArithmeticException e) {
+ assertTrue("should have found inverse for " + a + " mod "
+ + mod, !one.equals(a.gcd(mod)));
+ }
+ }
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#shiftRight(int)
+ */
+ public void test_shiftRightI() {
+ assertTrue("1 >> 0", BigInteger.valueOf(1).shiftRight(0).equals(
+ BigInteger.ONE));
+ assertTrue("1 >> 1", BigInteger.valueOf(1).shiftRight(1).equals(
+ BigInteger.ZERO));
+ assertTrue("1 >> 63", BigInteger.valueOf(1).shiftRight(63).equals(
+ BigInteger.ZERO));
+ assertTrue("1 >> 64", BigInteger.valueOf(1).shiftRight(64).equals(
+ BigInteger.ZERO));
+ assertTrue("1 >> 65", BigInteger.valueOf(1).shiftRight(65).equals(
+ BigInteger.ZERO));
+ assertTrue("1 >> 1000", BigInteger.valueOf(1).shiftRight(1000).equals(
+ BigInteger.ZERO));
+ assertTrue("-1 >> 0", BigInteger.valueOf(-1).shiftRight(0).equals(
+ minusOne));
+ assertTrue("-1 >> 1", BigInteger.valueOf(-1).shiftRight(1).equals(
+ minusOne));
+ assertTrue("-1 >> 63", BigInteger.valueOf(-1).shiftRight(63).equals(
+ minusOne));
+ assertTrue("-1 >> 64", BigInteger.valueOf(-1).shiftRight(64).equals(
+ minusOne));
+ assertTrue("-1 >> 65", BigInteger.valueOf(-1).shiftRight(65).equals(
+ minusOne));
+ assertTrue("-1 >> 1000", BigInteger.valueOf(-1).shiftRight(1000)
+ .equals(minusOne));
+
+ BigInteger a = BigInteger.ONE;
+ BigInteger c = bi3;
+ BigInteger E = bi3.negate();
+ BigInteger e = E;
+ for (int i = 0; i < 200; i++) {
+ BigInteger b = BigInteger.ZERO.setBit(i);
+ assertTrue("a==b", a.equals(b));
+ a = a.shiftLeft(1);
+ assertTrue("a non-neg", a.signum() >= 0);
+
+ BigInteger d = bi3.shiftRight(i);
+ assertTrue("c==d", c.equals(d));
+ c = c.shiftRight(1);
+ assertTrue(">>1 == /2", d.divide(two).equals(c));
+ assertTrue("c non-neg", c.signum() >= 0);
+
+ BigInteger f = E.shiftRight(i);
+ assertTrue("e==f", e.equals(f));
+ e = e.shiftRight(1);
+ assertTrue(">>1 == /2", f.subtract(one).divide(two).equals(e));
+ assertTrue("e negative", e.signum() == -1);
+
+ assertTrue("b >> i", b.shiftRight(i).equals(one));
+ assertTrue("b >> i+1", b.shiftRight(i + 1).equals(zero));
+ assertTrue("b >> i-1", b.shiftRight(i - 1).equals(two));
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#shiftLeft(int)
+ */
+ public void test_shiftLeftI() {
+ assertTrue("1 << 0", one.shiftLeft(0).equals(one));
+ assertTrue("1 << 1", one.shiftLeft(1).equals(two));
+ assertTrue("1 << 63", one.shiftLeft(63).equals(
+ new BigInteger("8000000000000000", 16)));
+ assertTrue("1 << 64", one.shiftLeft(64).equals(
+ new BigInteger("10000000000000000", 16)));
+ assertTrue("1 << 65", one.shiftLeft(65).equals(
+ new BigInteger("20000000000000000", 16)));
+ assertTrue("-1 << 0", minusOne.shiftLeft(0).equals(minusOne));
+ assertTrue("-1 << 1", minusOne.shiftLeft(1).equals(minusTwo));
+ assertTrue("-1 << 63", minusOne.shiftLeft(63).equals(
+ new BigInteger("-9223372036854775808")));
+ assertTrue("-1 << 64", minusOne.shiftLeft(64).equals(
+ new BigInteger("-18446744073709551616")));
+ assertTrue("-1 << 65", minusOne.shiftLeft(65).equals(
+ new BigInteger("-36893488147419103232")));
+
+ BigInteger a = bi3;
+ BigInteger c = minusOne;
+ for (int i = 0; i < 200; i++) {
+ BigInteger b = bi3.shiftLeft(i);
+ assertTrue("a==b", a.equals(b));
+ assertTrue("a >> i == bi3", a.shiftRight(i).equals(bi3));
+ a = a.shiftLeft(1);
+ assertTrue("<<1 == *2", b.multiply(two).equals(a));
+ assertTrue("a non-neg", a.signum() >= 0);
+ assertTrue("a.bitCount==b.bitCount", a.bitCount() == b.bitCount());
+
+ BigInteger d = minusOne.shiftLeft(i);
+ assertTrue("c==d", c.equals(d));
+ c = c.shiftLeft(1);
+ assertTrue("<<1 == *2 negative", d.multiply(two).equals(c));
+ assertTrue("c negative", c.signum() == -1);
+ assertTrue("d >> i == minusOne", d.shiftRight(i).equals(minusOne));
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#multiply(java.math.BigInteger)
+ */
+ public void test_multiplyLjava_math_BigInteger() {
+ assertTrue("Incorrect sum--wanted three zillion", aZillion
+ .add(aZillion).add(aZillion).equals(
+ aZillion.multiply(new BigInteger("3", 10))));
+
+ assertTrue("0*0", zero.multiply(zero).equals(zero));
+ assertTrue("0*1", zero.multiply(one).equals(zero));
+ assertTrue("1*0", one.multiply(zero).equals(zero));
+ assertTrue("1*1", one.multiply(one).equals(one));
+ assertTrue("0*(-1)", zero.multiply(minusOne).equals(zero));
+ assertTrue("(-1)*0", minusOne.multiply(zero).equals(zero));
+ assertTrue("(-1)*(-1)", minusOne.multiply(minusOne).equals(one));
+ assertTrue("1*(-1)", one.multiply(minusOne).equals(minusOne));
+ assertTrue("(-1)*1", minusOne.multiply(one).equals(minusOne));
+
+ testAllMults(bi1, bi1, bi11);
+ testAllMults(bi2, bi2, bi22);
+ testAllMults(bi3, bi3, bi33);
+ testAllMults(bi1, bi2, bi12);
+ testAllMults(bi1, bi3, bi13);
+ testAllMults(bi2, bi3, bi23);
+ }
+
+ /**
+ * @tests java.math.BigInteger#divide(java.math.BigInteger)
+ */
+ public void test_divideLjava_math_BigInteger() {
+ testAllDivs(bi33, bi3);
+ testAllDivs(bi22, bi2);
+ testAllDivs(bi11, bi1);
+ testAllDivs(bi13, bi1);
+ testAllDivs(bi13, bi3);
+ testAllDivs(bi12, bi1);
+ testAllDivs(bi12, bi2);
+ testAllDivs(bi23, bi2);
+ testAllDivs(bi23, bi3);
+ testAllDivs(largePos, bi1);
+ testAllDivs(largePos, bi2);
+ testAllDivs(largePos, bi3);
+ testAllDivs(largeNeg, bi1);
+ testAllDivs(largeNeg, bi2);
+ testAllDivs(largeNeg, bi3);
+ testAllDivs(largeNeg, largePos);
+ testAllDivs(largePos, largeNeg);
+ testAllDivs(bi3, bi3);
+ testAllDivs(bi2, bi2);
+ testAllDivs(bi1, bi1);
+ testDivRanges(bi1);
+ testDivRanges(bi2);
+ testDivRanges(bi3);
+ testDivRanges(smallPos);
+ testDivRanges(largePos);
+ testDivRanges(new BigInteger("62EB40FEF85AA9EB", 16));
+ testAllDivs(BigInteger.valueOf(0xCC0225953CL), BigInteger
+ .valueOf(0x1B937B765L));
+
+ try {
+ largePos.divide(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi1.divide(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi3.negate().divide(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ zero.divide(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#remainder(java.math.BigInteger)
+ */
+ public void test_remainderLjava_math_BigInteger() {
+ try {
+ largePos.remainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi1.remainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi3.negate().remainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ zero.remainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#mod(java.math.BigInteger)
+ */
+ public void test_modLjava_math_BigInteger() {
+ try {
+ largePos.mod(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi1.mod(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi3.negate().mod(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ zero.mod(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#divideAndRemainder(java.math.BigInteger)
+ */
+ public void test_divideAndRemainderLjava_math_BigInteger() {
+ try {
+ largePos.divideAndRemainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi1.divideAndRemainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ bi3.negate().divideAndRemainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+
+ try {
+ zero.divideAndRemainder(zero);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException e) {
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(java.lang.String)
+ */
+ public void test_ConstructorLjava_lang_String() {
+ assertTrue("new(0)", new BigInteger("0").equals(BigInteger.valueOf(0)));
+ assertTrue("new(1)", new BigInteger("1").equals(BigInteger.valueOf(1)));
+ assertTrue("new(12345678901234)", new BigInteger("12345678901234")
+ .equals(BigInteger.valueOf(12345678901234L)));
+ assertTrue("new(-1)", new BigInteger("-1").equals(BigInteger
+ .valueOf(-1)));
+ assertTrue("new(-12345678901234)", new BigInteger("-12345678901234")
+ .equals(BigInteger.valueOf(-12345678901234L)));
+ }
+
+ /**
+ * @tests java.math.BigInteger#BigInteger(java.lang.String, int)
+ */
+ public void test_ConstructorLjava_lang_StringI() {
+ assertTrue("new(0,16)", new BigInteger("0", 16).equals(BigInteger
+ .valueOf(0)));
+ assertTrue("new(1,16)", new BigInteger("1", 16).equals(BigInteger
+ .valueOf(1)));
+ assertTrue("new(ABF345678901234,16)", new BigInteger("ABF345678901234",
+ 16).equals(BigInteger.valueOf(0xABF345678901234L)));
+ assertTrue("new(abf345678901234,16)", new BigInteger("abf345678901234",
+ 16).equals(BigInteger.valueOf(0xABF345678901234L)));
+ assertTrue("new(-1,16)", new BigInteger("-1", 16).equals(BigInteger
+ .valueOf(-1)));
+ assertTrue("new(-ABF345678901234,16)", new BigInteger(
+ "-ABF345678901234", 16).equals(BigInteger
+ .valueOf(-0xABF345678901234L)));
+ assertTrue("new(-abf345678901234,16)", new BigInteger(
+ "-abf345678901234", 16).equals(BigInteger
+ .valueOf(-0xABF345678901234L)));
+ assertTrue("new(-101010101,2)", new BigInteger("-101010101", 2)
+ .equals(BigInteger.valueOf(-341)));
+ }
+
+ /**
+ * @tests java.math.BigInteger#toString()
+ */
+ public void test_toString() {
+ assertTrue("0.toString", "0".equals(BigInteger.valueOf(0).toString()));
+ assertTrue("1.toString", "1".equals(BigInteger.valueOf(1).toString()));
+ assertTrue("12345678901234.toString", "12345678901234"
+ .equals(BigInteger.valueOf(12345678901234L).toString()));
+ assertTrue("-1.toString", "-1"
+ .equals(BigInteger.valueOf(-1).toString()));
+ assertTrue("-12345678901234.toString", "-12345678901234"
+ .equals(BigInteger.valueOf(-12345678901234L).toString()));
+ }
+
+ /**
+ * @tests java.math.BigInteger#toString(int)
+ */
+ public void test_toStringI() {
+ assertTrue("0.toString(16)", "0".equals(BigInteger.valueOf(0).toString(
+ 16)));
+ assertTrue("1.toString(16)", "1".equals(BigInteger.valueOf(1).toString(
+ 16)));
+ assertTrue("ABF345678901234.toString(16)", "abf345678901234"
+ .equals(BigInteger.valueOf(0xABF345678901234L).toString(16)));
+ assertTrue("-1.toString(16)", "-1".equals(BigInteger.valueOf(-1)
+ .toString(16)));
+ assertTrue("-ABF345678901234.toString(16)", "-abf345678901234"
+ .equals(BigInteger.valueOf(-0xABF345678901234L).toString(16)));
+ assertTrue("-101010101.toString(2)", "-101010101".equals(BigInteger
+ .valueOf(-341).toString(2)));
+ }
+
+ /**
+ * @tests java.math.BigInteger#and(java.math.BigInteger)
+ */
+ public void test_andLjava_math_BigInteger() {
+ for (BigInteger[] element : booleanPairs) {
+ BigInteger i1 = element[0], i2 = element[1];
+ BigInteger res = i1.and(i2);
+ assertTrue("symmetry of and", res.equals(i2.and(i1)));
+ int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+ for (int i = 0; i < len; i++) {
+ assertTrue("and", (i1.testBit(i) && i2.testBit(i)) == res
+ .testBit(i));
+ }
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#or(java.math.BigInteger)
+ */
+ public void test_orLjava_math_BigInteger() {
+ for (BigInteger[] element : booleanPairs) {
+ BigInteger i1 = element[0], i2 = element[1];
+ BigInteger res = i1.or(i2);
+ assertTrue("symmetry of or", res.equals(i2.or(i1)));
+ int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+ for (int i = 0; i < len; i++) {
+ assertTrue("or", (i1.testBit(i) || i2.testBit(i)) == res
+ .testBit(i));
+ }
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#xor(java.math.BigInteger)
+ */
+ public void test_xorLjava_math_BigInteger() {
+ for (BigInteger[] element : booleanPairs) {
+ BigInteger i1 = element[0], i2 = element[1];
+ BigInteger res = i1.xor(i2);
+ assertTrue("symmetry of xor", res.equals(i2.xor(i1)));
+ int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+ for (int i = 0; i < len; i++) {
+ assertTrue("xor", (i1.testBit(i) ^ i2.testBit(i)) == res
+ .testBit(i));
+ }
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#not()
+ */
+ public void test_not() {
+ for (BigInteger[] element : booleanPairs) {
+ BigInteger i1 = element[0];
+ BigInteger res = i1.not();
+ int len = i1.bitLength() + 66;
+ for (int i = 0; i < len; i++) {
+ assertTrue("not", !i1.testBit(i) == res.testBit(i));
+ }
+ }
+ }
+
+ /**
+ * @tests java.math.BigInteger#andNot(java.math.BigInteger)
+ */
+ public void test_andNotLjava_math_BigInteger() {
+ for (BigInteger[] element : booleanPairs) {
+ BigInteger i1 = element[0], i2 = element[1];
+ BigInteger res = i1.andNot(i2);
+ int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
+ for (int i = 0; i < len; i++) {
+ assertTrue("andNot", (i1.testBit(i) && !i2.testBit(i)) == res
+ .testBit(i));
+ }
+ // asymmetrical
+ i1 = element[1];
+ i2 = element[0];
+ res = i1.andNot(i2);
+ for (int i = 0; i < len; i++) {
+ assertTrue("andNot reversed",
+ (i1.testBit(i) && !i2.testBit(i)) == res.testBit(i));
+ }
+ }
+ //regression for HARMONY-4653
+ try{
+ BigInteger.ZERO.andNot(null);
+ fail("should throw NPE");
+ }catch(Exception e){
+ //expected
+ }
+ BigInteger bi = new BigInteger(0, new byte[]{});
+ assertEquals(BigInteger.ZERO, bi.andNot(BigInteger.ZERO));
+ }
+
+
+ public void testClone() {
+ // Regression test for HARMONY-1770
+ MyBigInteger myBigInteger = new MyBigInteger("12345");
+ myBigInteger = (MyBigInteger) myBigInteger.clone();
+ }
+
+ static class MyBigInteger extends BigInteger implements Cloneable {
+ public MyBigInteger(String val) {
+ super(val);
+ }
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ return null;
+ }
+ }
+ }
+
+ @Override
+ protected void setUp() {
+ bi1 = new BigInteger("2436798324768978", 16);
+ bi2 = new BigInteger("4576829475724387584378543764555", 16);
+ bi3 = new BigInteger("43987298363278574365732645872643587624387563245",
+ 16);
+
+ bi33 = new BigInteger(
+ "10730846694701319120609898625733976090865327544790136667944805934175543888691400559249041094474885347922769807001",
+ 10);
+ bi22 = new BigInteger(
+ "33301606932171509517158059487795669025817912852219962782230629632224456249",
+ 10);
+ bi11 = new BigInteger("6809003003832961306048761258711296064", 10);
+ bi23 = new BigInteger(
+ "597791300268191573513888045771594235932809890963138840086083595706565695943160293610527214057",
+ 10);
+ bi13 = new BigInteger(
+ "270307912162948508387666703213038600031041043966215279482940731158968434008",
+ 10);
+ bi12 = new BigInteger(
+ "15058244971895641717453176477697767050482947161656458456", 10);
+
+ largePos = new BigInteger(
+ "834759814379857314986743298675687569845986736578576375675678998612743867438632986243982098437620983476924376",
+ 16);
+ smallPos = new BigInteger("48753269875973284765874598630960986276", 16);
+ largeNeg = new BigInteger(
+ "-878824397432651481891353247987891423768534321387864361143548364457698487264387568743568743265873246576467643756437657436587436",
+ 16);
+ smallNeg = new BigInteger("-567863254343798609857456273458769843", 16);
+ booleanPairs = new BigInteger[][] { { largePos, smallPos },
+ { largePos, smallNeg }, { largeNeg, smallPos },
+ { largeNeg, smallNeg } };
+ }
+
+ private void testDiv(BigInteger i1, BigInteger i2) {
+ BigInteger q = i1.divide(i2);
+ BigInteger r = i1.remainder(i2);
+ BigInteger[] temp = i1.divideAndRemainder(i2);
+
+ assertTrue("divide and divideAndRemainder do not agree", q
+ .equals(temp[0]));
+ assertTrue("remainder and divideAndRemainder do not agree", r
+ .equals(temp[1]));
+ assertTrue("signum and equals(zero) do not agree on quotient", q
+ .signum() != 0
+ || q.equals(zero));
+ assertTrue("signum and equals(zero) do not agree on remainder", r
+ .signum() != 0
+ || r.equals(zero));
+ assertTrue("wrong sign on quotient", q.signum() == 0
+ || q.signum() == i1.signum() * i2.signum());
+ assertTrue("wrong sign on remainder", r.signum() == 0
+ || r.signum() == i1.signum());
+ assertTrue("remainder out of range", r.abs().compareTo(i2.abs()) < 0);
+ assertTrue("quotient too small", q.abs().add(one).multiply(i2.abs())
+ .compareTo(i1.abs()) > 0);
+ assertTrue("quotient too large", q.abs().multiply(i2.abs()).compareTo(
+ i1.abs()) <= 0);
+ BigInteger p = q.multiply(i2);
+ BigInteger a = p.add(r);
+ assertTrue("(a/b)*b+(a%b) != a", a.equals(i1));
+ try {
+ BigInteger mod = i1.mod(i2);
+ assertTrue("mod is negative", mod.signum() >= 0);
+ assertTrue("mod out of range", mod.abs().compareTo(i2.abs()) < 0);
+ assertTrue("positive remainder == mod", r.signum() < 0
+ || r.equals(mod));
+ assertTrue("negative remainder == mod - divisor", r.signum() >= 0
+ || r.equals(mod.subtract(i2)));
+ } catch (ArithmeticException e) {
+ assertTrue("mod fails on negative divisor only", i2.signum() <= 0);
+ }
+ }
+
+ private void testDivRanges(BigInteger i) {
+ BigInteger bound = i.multiply(two);
+ for (BigInteger j = bound.negate(); j.compareTo(bound) <= 0; j = j
+ .add(i)) {
+ BigInteger innerbound = j.add(two);
+ BigInteger k = j.subtract(two);
+ for (; k.compareTo(innerbound) <= 0; k = k.add(one)) {
+ testDiv(k, i);
+ }
+ }
+ }
+
+ private boolean isPrime(long b) {
+ if (b == 2) {
+ return true;
+ }
+ // check for div by 2
+ if ((b & 1L) == 0) {
+ return false;
+ }
+ long maxlen = ((long) Math.sqrt(b)) + 2;
+ for (long x = 3; x < maxlen; x += 2) {
+ if (b % x == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void testAllMults(BigInteger i1, BigInteger i2, BigInteger ans) {
+ assertTrue("i1*i2=ans", i1.multiply(i2).equals(ans));
+ assertTrue("i2*i1=ans", i2.multiply(i1).equals(ans));
+ assertTrue("-i1*i2=-ans", i1.negate().multiply(i2).equals(ans.negate()));
+ assertTrue("-i2*i1=-ans", i2.negate().multiply(i1).equals(ans.negate()));
+ assertTrue("i1*-i2=-ans", i1.multiply(i2.negate()).equals(ans.negate()));
+ assertTrue("i2*-i1=-ans", i2.multiply(i1.negate()).equals(ans.negate()));
+ assertTrue("-i1*-i2=ans", i1.negate().multiply(i2.negate()).equals(ans));
+ assertTrue("-i2*-i1=ans", i2.negate().multiply(i1.negate()).equals(ans));
+ }
+
+ private void testAllDivs(BigInteger i1, BigInteger i2) {
+ testDiv(i1, i2);
+ testDiv(i1.negate(), i2);
+ testDiv(i1, i2.negate());
+ testDiv(i1.negate(), i2.negate());
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
new file mode 100644
index 0000000..a349b9c
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+public class ASCCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("ascii");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 1, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() {
+ // FIXME: different here
+ return null;
+ // ByteBuffer buffer = ByteBuffer.allocate(8);
+ // buffer.put((byte)-1);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+
+ }
+
+ ByteBuffer getMalformedByteBuffer() {
+ // FIXME: different here
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ buffer.put((byte) -1);
+ buffer.put(getByteBuffer());
+ buffer.flip();
+ return buffer;
+
+ // TODO: how malform?
+ // return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
new file mode 100644
index 0000000..f46321e
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ASCCharsetTest.java
@@ -0,0 +1,59 @@
+/* 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;
+
+/**
+ * Test charset US-ASCII.
+ */
+public class ASCCharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ *
+ */
+ public ASCCharsetTest(String arg0) {
+ super(arg0, "US-ASCII", new String[] { "ISO646-US", "ASCII", "cp367",
+ "ascii7", "ANSI_X3.4-1986", "iso-ir-6", "us", "646",
+ "iso_646.irv:1983", "csASCII", "ANSI_X3.4-1968",
+ "ISO_646.irv:1991" }, true, true); // "ibm-367"
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98,
+ this.testingCharset.newEncoder().replacement()[0],
+ this.testingCharset.newEncoder().replacement()[0] };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, 63, 63 };
+ char[] output = "ab??".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
new file mode 100644
index 0000000..0ebf922
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/AbstractCharsetTestCase.java
@@ -0,0 +1,175 @@
+/*
+ * 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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+
+import junit.framework.TestCase;
+
+/**
+ * Super class for concrete charset test suites.
+ */
+public abstract class AbstractCharsetTestCase extends TestCase {
+
+ // the canonical name of this charset
+ protected final String canonicalName;
+
+ // the aliases set
+ protected final String[] aliases;
+
+ // canEncode
+ protected final boolean canEncode;
+
+ // isRegistered
+ protected final boolean isRegistered;
+
+ // charset instance
+ protected Charset testingCharset;
+
+ /*
+ * Initialize the field "testingCharset" here.
+ *
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.testingCharset = Charset.forName(this.canonicalName);
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Constructor for ConcreteCharsetTest.
+ *
+ */
+ public AbstractCharsetTestCase(String arg0, String canonicalName,
+ String[] aliases, boolean canEncode, boolean isRegistered) {
+ super(arg0);
+ this.canonicalName = canonicalName;
+ this.canEncode = canEncode;
+ this.isRegistered = isRegistered;
+ this.aliases = aliases;
+ }
+
+ /*
+ * Test canEncode.
+ */
+ public void testCanEncode() {
+ assertEquals(this.canEncode, this.testingCharset.canEncode());
+ }
+
+ /*
+ * Test isRegistered.
+ */
+ public void testIsRegistered() {
+ assertEquals(this.isRegistered, this.testingCharset.isRegistered());
+ }
+
+ /*
+ * Test name.
+ */
+ public void testName() {
+ assertEquals(this.canonicalName, this.testingCharset.name());
+ // assertEquals(this.canonicalName, this.testingCharset.displayName());
+ // assertEquals(this.canonicalName,
+ // this.testingCharset.displayName(null));
+ }
+
+ /*
+ * Test aliases.
+ */
+ public void testAliases() {
+ for (int i = 0; i < this.aliases.length; i++) {
+ Charset c = Charset.forName(this.aliases[i]);
+ assertEquals(this.canonicalName, c.name());
+ // TODO
+ // assertTrue(this.testingCharset.aliases().contains(this.aliases[i]));
+ }
+ }
+
+ /*
+ * Test the method encode(String) with null.
+ */
+ public void testEncode_String_Null() {
+ try {
+ this.testingCharset.encode((String) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test the method encode(CharBuffer) with null.
+ */
+ public void testEncode_CharBuffer_Null() {
+ try {
+ this.testingCharset.encode((CharBuffer) null);
+ fail("Should throw NullPointerException!");
+ } catch (NullPointerException e) {
+ // expected
+ }
+ }
+
+ /*
+ * Test encoding.
+ */
+ protected void internalTestEncode(String input, byte[] output) {
+ ByteBuffer bb = this.testingCharset.encode(input);
+ int i = 0;
+ bb.rewind();
+ while (bb.hasRemaining() && i < output.length) {
+ assertEquals(output[i], bb.get());
+ i++;
+ }
+ assertFalse(bb.hasRemaining());
+ assertEquals(output.length, i);
+ }
+
+ /*
+ * Test encoding.
+ */
+ public abstract void testEncode_Normal();
+
+ /*
+ * Test decoding.
+ */
+ protected void internalTestDecode(byte[] input, char[] output) {
+ CharBuffer chb = this.testingCharset.decode(ByteBuffer.wrap(input));
+ int i = 0;
+ chb.rewind();
+ while (chb.hasRemaining() && i < output.length) {
+ assertEquals(output[i], chb.get());
+ i++;
+ }
+ assertFalse(chb.hasRemaining());
+ assertEquals(output.length, i);
+ }
+
+ /*
+ * Test decoding.
+ */
+ public abstract void testDecode_Normal();
+}
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
new file mode 100644
index 0000000..9cd59ea
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetDecoderTest.java
@@ -0,0 +1,870 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.CharsetDecoder
+ */
+public class CharsetDecoderTest extends TestCase {
+
+ protected static final int MAX_BYTES = 3;
+
+ protected static final double AVER_BYTES = 0.5;
+
+ // default charset
+ private static final Charset MOCKCS = new CharsetEncoderTest.MockCharset(
+ "mock", new String[0]);
+
+ Charset cs = MOCKCS;
+
+ // default decoder
+ protected static CharsetDecoder decoder;
+
+ String bom = "";
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ decoder = cs.newDecoder();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // /*
+ // * test default value
+ // */
+ // public void testDefaultCharsPerByte() {
+ // assertTrue(decoder.averageCharsPerByte() == AVER_BYTES);
+ // assertTrue(decoder.maxCharsPerByte() == MAX_BYTES);
+ // }
+
+ public void testDefaultValues() {
+ assertSame(cs, decoder.charset());
+ try {
+ decoder.detectedCharset();
+ fail("should unsupported");
+ } catch (UnsupportedOperationException e) {
+ }
+ try {
+ assertTrue(decoder.isCharsetDetected());
+ fail("should unsupported");
+ } catch (UnsupportedOperationException e) {
+ }
+ assertFalse(decoder.isAutoDetecting());
+ assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+ assertSame(CodingErrorAction.REPORT, decoder
+ .unmappableCharacterAction());
+ assertEquals(decoder.replacement(), "\ufffd");
+ }
+
+ /*
+ * test constructor
+ */
+ public void testCharsetDecoder() {
+ // default value
+ decoder = new MockCharsetDecoder(cs, (float) AVER_BYTES, MAX_BYTES);
+
+ // normal case
+ CharsetDecoder ec = new MockCharsetDecoder(cs, 1, MAX_BYTES);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+ assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // Normal case: null charset
+ ec = new MockCharsetDecoder(null, 1, MAX_BYTES);
+ assertNull(ec.charset());
+ assertEquals(1.0, ec.averageCharsPerByte(), 0.0);
+ assertTrue(ec.maxCharsPerByte() == MAX_BYTES);
+
+ ec = new MockCharsetDecoder(new CharsetEncoderTest.MockCharset("mock",
+ new String[0]), 1, MAX_BYTES);
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // // OK: average length less than max length
+ // ec = new MockCharsetDecoder(cs, MAX_BYTES, 1);
+ // assertTrue(ec.averageCharsPerByte() == MAX_BYTES);
+ // assertTrue(ec.maxCharsPerByte() == 1);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetDecoder(cs, 0, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetDecoder(cs, 1, 0);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetDecoder(cs, -1, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetDecoder(cs, 1, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * test onMalformedInput
+ */
+ public void testOnMalformedInput() {
+ assertSame(CodingErrorAction.REPORT, decoder.malformedInputAction());
+ try {
+ decoder.onMalformedInput(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, decoder.malformedInputAction());
+ }
+
+ /*
+ * test unmappableCharacter
+ */
+ public void testOnUnmappableCharacter() {
+ assertSame(CodingErrorAction.REPORT, decoder
+ .unmappableCharacterAction());
+ try {
+ decoder.onUnmappableCharacter(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, decoder
+ .unmappableCharacterAction());
+ }
+
+ /*
+ * test replaceWith
+ */
+ public void testReplaceWith() {
+ try {
+ decoder.replaceWith(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ decoder.replaceWith("");
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ decoder.replaceWith("testReplaceWith");
+ fail("should throw illegal argument exception");
+ } catch (IllegalArgumentException e) {
+ }
+
+ decoder.replaceWith("a");
+ assertSame("a", decoder.replacement());
+ }
+
+ /*
+ * Class under test for CharBuffer decode(ByteBuffer)
+ */
+ public void testDecodeByteBuffer() throws CharacterCodingException {
+ implTestDecodeByteBuffer();
+ }
+
+ void implTestDecodeByteBuffer() throws CharacterCodingException {
+ // Null pointer
+ try {
+ decoder.decode(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // empty input buffer
+ CharBuffer out = decoder.decode(ByteBuffer.allocate(0));
+ assertCharBufferValue("", out);
+
+ // normal case
+ ByteBuffer in = getByteBuffer();
+ out = decoder.decode(in);
+ assertEquals(0, out.position());
+ assertEquals(getString().length(), out.limit());
+ assertEquals(getString().length(), out.remaining());
+ assertCharBufferValue(getString(), out);
+
+ // normal read only case
+ in = getByteBuffer().asReadOnlyBuffer();
+ out = decoder.decode(in);
+ assertEquals(out.position(), 0);
+ assertEquals(out.limit(), getString().length());
+ assertEquals(out.remaining(), getString().length());
+ assertCharBufferValue(getString(), out);
+ }
+
+ public void testDecodeByteBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ CharBuffer out;
+ ByteBuffer in;
+ String replaceStr = decoder.replacement() + getString();
+
+ // MalformedException:
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ in = getMalformedByteBuffer();
+ if (in != null) {
+ try {
+ CharBuffer buffer = decoder.decode(in);
+ assertTrue(buffer.remaining() > 0);
+ fail("should throw MalformedInputException");
+ } catch (MalformedInputException e) {
+ }
+
+ decoder.reset();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ out = decoder.decode(in);
+ assertCharBufferValue(getString(), out);
+
+ decoder.reset();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ out = decoder.decode(in);
+ assertCharBufferValue(replaceStr, out);
+ }
+
+ // Unmapped Exception:
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ in = getUnmappedByteBuffer();
+ if (in != null) {
+ try {
+ decoder.decode(in);
+ fail("should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException e) {
+ }
+
+ decoder.reset();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ out = decoder.decode(in);
+ assertCharBufferValue(getString(), out);
+
+ decoder.reset();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ out = decoder.decode(in);
+ assertCharBufferValue(replaceStr, out);
+ }
+
+ // RuntimeException
+ try {
+ decoder.decode(getExceptionByteArray());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ /*
+ * Class under test for CoderResult decode(ByteBuffer, CharBuffer, boolean)
+ */
+ public void testDecodeByteBufferCharBuffer() {
+ implTestDecodeByteBufferCharBuffer(getByteBuffer());
+ }
+
+ public void testDecodeByteBufferCharBufferReadOnly() {
+ implTestDecodeByteBufferCharBuffer(getByteBuffer());
+ }
+
+ void implTestDecodeByteBufferCharBuffer(ByteBuffer in) {
+ CharBuffer out = CharBuffer.allocate(100);
+
+ // Null pointer
+ decoder.reset();
+ try {
+ decoder.decode(null, out, true);
+ fail("NullPointerException expected");
+ } catch (NullPointerException e) {
+ }
+ try {
+ decoder.decode(in, null, true);
+ fail("NullPointerException expected");
+ } catch (NullPointerException e) {
+ }
+
+ // normal case, one complete operation
+ decoder.reset();
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertEquals(out.limit(), 100);
+ assertEquals(out.position(), getString().length());
+ assertEquals(out.remaining(), 100 - getString().length());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(getString(), out);
+ decoder.flush(out);
+
+ // normal case, one complete operation, but call twice, first time set
+ // endOfInput to false
+ decoder.reset();
+ in.rewind();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ assertEquals(out.limit(), 100);
+ assertEquals(out.position(), getString().length());
+ assertEquals(out.remaining(), 100 - getString().length());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(getString(), out);
+
+ decoder.reset();
+ in.rewind();
+ out.clear();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ in = getHeadlessByteBuffer();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertEquals(out.limit(), 100);
+ assertTrue(out.position() > 0);
+ assertEquals(out.remaining(), out.capacity() - out.position());
+ assertEquals(out.capacity(), 100);
+ assertCharBufferValue(getString() + getString() + getString(), out);
+
+ // overflow
+ out = CharBuffer.allocate(4);
+ decoder.reset();
+ in = getByteBuffer();
+ out.rewind();
+ assertSame(CoderResult.OVERFLOW, decoder.decode(in, out, false));
+
+ assertCharBufferValue(getString().substring(0, 4), out);
+ out = CharBuffer.allocate(100);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, false));
+ assertCharBufferValue(getString().substring(4), out);
+ in.rewind();
+ out = CharBuffer.allocate(100);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, true));
+ assertCharBufferValue(bom + getString(), out);
+ }
+
+ public void testDecodeCharBufferByteBufferUnmappedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferUnmappedException(
+ getUnmappedByteBuffer(), true);
+ }
+
+ public void testDecodeCharBufferByteIncompleteBufferUnmappedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferUnmappedException(
+ getUnmappedByteBuffer(), false);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyBufferUnmappedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferUnmappedException(
+ readOnly(getUnmappedByteBuffer()), true);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyIncompleteBufferUnmappedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferUnmappedException(
+ readOnly(getUnmappedByteBuffer()), false);
+ }
+
+ void implTestDecodeCharBufferByteBufferUnmappedException(ByteBuffer in,
+ boolean endOfInput) throws CharacterCodingException,
+ UnsupportedEncodingException {
+ if (null == in) {
+ return;
+ }
+ CharBuffer out = CharBuffer.allocate(50);
+
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ decoder.reset();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ CoderResult result = decoder.decode(in, out, endOfInput);
+ assertTrue(result.isUnmappable());
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+ assertCharBufferValue(getString(), out);
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+ assertCharBufferValue(decoder.replacement() + getString(), out);
+ }
+
+ public void testDecodeCharBufferByteBufferMalformedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferMalformedException(
+ getMalformedByteBuffer(), true);
+ }
+
+ public void testDecodeCharBufferByteIncompleteBufferMalformedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+
+ implTestDecodeCharBufferByteBufferMalformedException(
+ getMalformedByteBuffer(), false);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyBufferMalformedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferMalformedException(
+ readOnly(getMalformedByteBuffer()), true);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyIncompleteBufferMalformedException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferMalformedException(
+ readOnly(getMalformedByteBuffer()), false);
+ }
+
+ void implTestDecodeCharBufferByteBufferMalformedException(ByteBuffer in,
+ boolean endOfInput) throws CharacterCodingException,
+ UnsupportedEncodingException {
+ if (null == in) {
+ return;
+ }
+ CharBuffer out = CharBuffer.allocate(getString().length() * 3);
+ decoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ decoder.reset();
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ CoderResult result = decoder.decode(in, out, endOfInput);
+ assertTrue(result.isMalformed());
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+ assertCharBufferValue(getString(), out);
+
+ decoder.reset();
+ out.clear();
+ in.rewind();
+ decoder.onMalformedInput(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, decoder.decode(in, out, endOfInput));
+ assertCharBufferValue(decoder.replacement() + getString(), out);
+ }
+
+ public void testDecodeCharBufferByteBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+ true);
+ }
+
+ public void testDecodeCharBufferByteIncompleteBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferException(getExceptionByteArray(),
+ false);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferException(
+ readOnly(getExceptionByteArray()), true);
+ }
+
+ public void testDecodeCharBufferByteReadOnlyIncompleteBufferException()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ implTestDecodeCharBufferByteBufferException(
+ readOnly(getExceptionByteArray()), false);
+ }
+
+ void implTestDecodeCharBufferByteBufferException(ByteBuffer in,
+ boolean endOfInput) throws CharacterCodingException,
+ UnsupportedEncodingException {
+ CharBuffer out = CharBuffer.allocate(50);
+ decoder.reset();
+ try {
+ decoder.decode(in, out, endOfInput);
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ private ByteBuffer readOnly(ByteBuffer b) {
+ if (null == b) {
+ return null;
+ }
+ return b.asReadOnlyBuffer();
+ }
+
+ protected String getString() {
+ return " buffer";
+ }
+
+ protected ByteBuffer getByteBuffer() {
+ return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114 });
+ }
+
+ protected ByteBuffer getHeadlessByteBuffer() {
+ return getByteBuffer();
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ // "runtime"
+ return ByteBuffer
+ .wrap(new byte[] { 114, 117, 110, 116, 105, 109, 101 });
+ }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // "unmap buffer"
+ byte[] ba = new byte[] { 117, 110, 109, 97, 112, 32, 98, 117, 102, 102,
+ 101, 114 };
+ return ByteBuffer.wrap(ba);
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ // "malform buffer"
+ byte[] ba = new byte[] { 109, 97, 108, 102, 111, 114, 109, 32, 98, 117,
+ 102, 102, 101, 114 };
+ return ByteBuffer.wrap(ba);
+ }
+
+ private void assertCharBufferValue(String expected, CharBuffer out) {
+ if (out.position() != 0) {
+ out.flip();
+ }
+ assertEquals(expected, new String(out.array(), out.arrayOffset(), out
+ .arrayOffset() + out.limit()));
+ }
+
+ /*
+ * test flush
+ */
+ public void testFlush() throws CharacterCodingException {
+ CharBuffer out = CharBuffer.allocate(10);
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 12, 12 });
+ decoder.decode(in, out, true);
+ assertSame(CoderResult.UNDERFLOW, decoder.flush(out));
+
+ decoder.reset();
+ decoder.decode((ByteBuffer) in.rewind(), (CharBuffer) out.rewind(),
+ true);
+ assertSame(CoderResult.UNDERFLOW, decoder
+ .flush(CharBuffer.allocate(10)));
+ }
+
+ /*
+ * ---------------------------------- methods to test illegal state
+ * -----------------------------------
+ */
+ // Normal case: just after reset, and it also means reset can be done
+ // anywhere
+ public void testResetIllegalState() throws CharacterCodingException {
+ decoder.reset();
+ decoder.decode(getByteBuffer());
+ decoder.reset();
+ decoder.decode(getByteBuffer(), CharBuffer.allocate(3), false);
+ decoder.reset();
+ decoder.decode(getByteBuffer(), CharBuffer.allocate(3), true);
+ decoder.reset();
+ }
+
+ public void testFlushIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(5);
+ // Normal case: after decode with endOfInput is true
+ decoder.reset();
+ decoder.decode(in, out, true);
+ out.rewind();
+ CoderResult result = decoder.flush(out);
+ assertSame(result, CoderResult.UNDERFLOW);
+
+ // Illegal state: flush twice
+ try {
+ decoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ }
+
+ // 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) {
+ }
+ }
+
+ // test illegal states for decode facade
+ public void testDecodeFacadeIllegalState() throws CharacterCodingException {
+ // decode facade can be execute in anywhere
+ ByteBuffer in = getByteBuffer();
+
+ // Normal case: just created
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after decode facade
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(getByteBuffer(), CharBuffer.allocate(30), false);
+ decoder.decode(in);
+ in.rewind();
+
+ // Normal case: just after flush
+ decoder.reset();
+ decoder.decode(getByteBuffer(), CharBuffer.allocate(30), true);
+ decoder.flush(CharBuffer.allocate(10));
+ decoder.decode(in);
+ in.rewind();
+ }
+
+ // test illegal states for two decode method with endOfInput is true
+ public void testDecodeTrueIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(100);
+ // Normal case: just created
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), false);
+ in.rewind();
+ decoder.decode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ decoder.flush(CharBuffer.allocate(10));
+ in.rewind();
+ try {
+ decoder.decode(in, out, true);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ }
+
+ // test illegal states for two decode method with endOfInput is false
+ public void testDecodeFalseIllegalState() throws CharacterCodingException {
+ ByteBuffer in = ByteBuffer.wrap(new byte[] { 98, 98 });
+ CharBuffer out = CharBuffer.allocate(5);
+ // Normal case: just created
+ decoder.decode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after decode facade
+ decoder.reset();
+ decoder.decode(in);
+ in.rewind();
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after decode with that endOfInput is true
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after decode with that endOfInput is false
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), false);
+ in.rewind();
+ decoder.decode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ decoder.reset();
+ decoder.decode(in, CharBuffer.allocate(30), true);
+ in.rewind();
+ decoder.flush(CharBuffer.allocate(10));
+ try {
+ decoder.decode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+ }
+
+ /*
+ * --------------------------------- illegal state test end
+ * ---------------------------------
+ */
+
+ public void testImplFlush() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+ .pubImplFlush(null));
+ }
+
+ public void testImplOnMalformedInput() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ assertEquals(CoderResult.UNDERFLOW, ((MockCharsetDecoder) decoder)
+ .pubImplFlush(null));
+
+ }
+
+ public void testImplOnUnmappableCharacter() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplOnUnmappableCharacter(null);
+ }
+
+ public void testImplReplaceWith() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplReplaceWith(null);
+ }
+
+ public void testImplReset() {
+ decoder = new MockCharsetDecoder(cs, 1, 3);
+ ((MockCharsetDecoder) decoder).pubImplReset();
+ }
+
+ /*
+ * mock decoder
+ */
+ public static class MockCharsetDecoder extends CharsetDecoder {
+ public MockCharsetDecoder(Charset cs, float ave, float max) {
+ super(cs, ave, max);
+ }
+
+ protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
+ int inPosition = in.position();
+ byte[] input = new byte[in.remaining()];
+ in.get(input);
+ String result;
+ try {
+ result = new String(input, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new AssertionError(e);
+ }
+ if (result.startsWith("malform")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // set the error length
+ return CoderResult.malformedForLength("malform".length());
+ } else if (result.startsWith("unmap")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // set the error length
+ return CoderResult.unmappableForLength("unmap".length());
+ } else if (result.startsWith("runtime")) {
+ // reset the cursor to the error position
+ in.position(0);
+ // set the error length
+ throw new RuntimeException("runtime");
+ }
+ int inLeft = input.length;
+ int outLeft = out.remaining();
+ CoderResult r = CoderResult.UNDERFLOW;
+ int length = inLeft;
+ if (outLeft < inLeft) {
+ r = CoderResult.OVERFLOW;
+ length = outLeft;
+ in.position(inPosition + outLeft);
+ }
+ for (int i = 0; i < length; i++) {
+ out.put((char) input[i]);
+ }
+ return r;
+ }
+
+ protected CoderResult implFlush(CharBuffer out) {
+ CoderResult result = super.implFlush(out);
+ if (out.remaining() >= 5) {
+ // TODO
+ // out.put("flush");
+ result = CoderResult.UNDERFLOW;
+ } else {
+ // out.put("flush", 0, out.remaining());
+ result = CoderResult.OVERFLOW;
+ }
+ return result;
+ }
+
+ public CoderResult pubImplFlush(CharBuffer out) {
+ return super.implFlush(out);
+ }
+
+ public void pubImplOnMalformedInput(CodingErrorAction newAction) {
+ super.implOnMalformedInput(newAction);
+ }
+
+ public void pubImplOnUnmappableCharacter(CodingErrorAction newAction) {
+ super.implOnUnmappableCharacter(newAction);
+ }
+
+ public void pubImplReplaceWith(String newReplacement) {
+ super.implReplaceWith(newReplacement);
+ }
+
+ public void pubImplReset() {
+ super.implReset();
+ }
+
+ }
+
+}
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
new file mode 100644
index 0000000..ef219be
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetEncoderTest.java
@@ -0,0 +1,1137 @@
+/* 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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * API unit test for java.nio.charset.CharsetEncoder
+ */
+public class CharsetEncoderTest extends TestCase {
+
+ static final int MAX_BYTES = 3;
+
+ static final float AVER_BYTES = 0.5f;
+
+ // charset for mock class
+ private static final Charset MOCKCS = new MockCharset("CharsetEncoderTest_mock", new String[0]);
+
+ Charset cs = MOCKCS;
+
+ // default encoder
+ CharsetEncoder encoder;
+
+ // default for Charset abstract class
+ byte[] defaultReplacement = new byte[] { 63 };
+
+ // specific for Charset implementation subclass
+ byte[] specifiedReplacement = new byte[] { 63 };
+
+ static final String unistr = " buffer";// \u8000\u8001\u00a5\u3000\r\n";
+
+ byte[] unibytes = new byte[] { 32, 98, 117, 102, 102, 101, 114 };
+
+ byte[] unibytesWithRep = null;
+
+ byte[] surrogate = new byte[0];
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ encoder = cs.newEncoder();
+ if (null == unibytesWithRep) {
+ byte[] replacement = encoder.replacement();
+ unibytesWithRep = new byte[replacement.length + unibytes.length];
+ System.arraycopy(replacement, 0, unibytesWithRep, 0,
+ replacement.length);
+ System.arraycopy(unibytes, 0, unibytesWithRep, replacement.length,
+ unibytes.length);
+ }
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testSpecificDefaultValue() {
+ assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+ assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+ }
+
+ public void testDefaultValue() {
+ assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ assertEquals(CodingErrorAction.REPORT, encoder.unmappableCharacterAction());
+ assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+ assertSame(encoder, encoder.onUnmappableCharacter(CodingErrorAction.IGNORE));
+ if (encoder instanceof MockCharsetEncoder) {
+ assertTrue(Arrays.equals(encoder.replacement(), defaultReplacement));
+ } else {
+ assertTrue(Arrays.equals(encoder.replacement(), specifiedReplacement));
+ }
+
+ }
+
+ /*
+ * Class under test for constructor CharsetEncoder(Charset, float, float)
+ */
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // default value
+ encoder = new MockCharsetEncoder(cs, (float) AVER_BYTES, MAX_BYTES);
+ assertSame(encoder.charset(), cs);
+ assertTrue(encoder.averageBytesPerChar() == AVER_BYTES);
+ assertTrue(encoder.maxBytesPerChar() == MAX_BYTES);
+ assertEquals(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ assertEquals(CodingErrorAction.REPORT, encoder
+ .unmappableCharacterAction());
+ assertEquals(new String(encoder.replacement()), new String(
+ defaultReplacement));
+ assertSame(encoder, encoder.onMalformedInput(CodingErrorAction.IGNORE));
+ assertSame(encoder, encoder
+ .onUnmappableCharacter(CodingErrorAction.IGNORE));
+
+ // normal case
+ CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageBytesPerChar(), 0);
+ assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // NullPointerException: null charset
+ try {
+ ec = new MockCharsetEncoder(null, 1, MAX_BYTES);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ ec = new MockCharsetEncoder(new MockCharset("mock", new String[0]), 1,
+ MAX_BYTES);
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // // OK: average length less than max length
+ // ec = new MockCharsetEncoder(cs, MAX_BYTES, 1);
+ // assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+ // assertTrue(ec.maxBytesPerChar() == 1);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetEncoder(cs, 0, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, 0);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetEncoder(cs, -1, MAX_BYTES);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, -1);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * Class under test for constructor CharsetEncoder(Charset, float, float,
+ * byte[])
+ */
+ public void testCharsetEncoderCharsetfloatfloatbyteArray() {
+ byte[] ba = getLegalByteArray();
+ // normal case
+ CharsetEncoder ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, ba);
+ assertSame(ec.charset(), cs);
+ assertEquals(1.0, ec.averageBytesPerChar(), 0.0);
+ assertTrue(ec.maxBytesPerChar() == MAX_BYTES);
+ assertSame(ba, ec.replacement());
+
+ /*
+ * ------------------------ Exceptional cases -------------------------
+ */
+ // NullPointerException: null charset
+ try {
+ ec = new MockCharsetEncoder(null, 1, MAX_BYTES, ba);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // Illegal Argument: null byte array
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, null);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ // Illegal Argument: empty byte array
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[0]);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ // Illegal Argument: byte array is longer than max length
+ try {
+ ec = new MockCharsetEncoder(cs, 1, MAX_BYTES, new byte[] { 1, 2,
+ MAX_BYTES, 4 });
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Commented out since the comment is wrong since MAX_BYTES > 1
+ // This test throws IllegalArgumentException on Harmony and RI
+ // // OK: average length less than max length
+ // ec = new MockCharsetEncoder(cs, MAX_BYTES, ba.length, ba);
+ // assertTrue(ec.averageBytesPerChar() == MAX_BYTES);
+ // assertTrue(ec.maxBytesPerChar() == ba.length);
+
+ // Illegal Argument: zero length
+ try {
+ ec = new MockCharsetEncoder(cs, 0, MAX_BYTES, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, 0, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+
+ // Illegal Argument: negative length
+ try {
+ ec = new MockCharsetEncoder(cs, -1, MAX_BYTES, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ ec = new MockCharsetEncoder(cs, 1, -1, ba);
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ /*
+ * Class under test for boolean canEncode(char)
+ */
+ public void testCanEncodechar() throws CharacterCodingException {
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ assertTrue(encoder.canEncode('\ud800'));
+ // valid surrogate pair
+ assertTrue(encoder.canEncode('\udc00'));
+ }
+
+ /*-----------------------------------------
+ * Class under test for illegal state case
+ * methods which can change internal states are two encode, flush, two canEncode, reset
+ * -----------------------------------------
+ */
+
+ // Normal case: just after reset, and it also means reset can be done
+ // anywhere
+ public void testResetIllegalState() throws CharacterCodingException {
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud901');
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud901\udc00");
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"));
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), false);
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("aaa"), ByteBuffer.allocate(3), true);
+ assertSame(encoder, encoder.reset());
+ }
+
+ 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: flush twice
+ try {
+ encoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+
+ // 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
+ }
+ }
+
+ public void testFlushAfterConstructing() {
+ ByteBuffer out = ByteBuffer.allocate(5);
+
+ //Illegal state: flush after instance created
+ try {
+ encoder.flush(out);
+ fail("should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ // Expected
+ }
+
+ }
+
+ // test illegal states for encode facade
+ public void testEncodeFacadeIllegalState() throws CharacterCodingException {
+ // encode facade can be execute in anywhere
+ CharBuffer in = CharBuffer.wrap("aaa");
+ // Normal case: just created
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after encode facade
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud902\udc00");
+ encoder.encode(in);
+ in.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud902');
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in);
+ in.rewind();
+
+ // Normal case: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ encoder.encode(in);
+ in.rewind();
+ }
+
+ // test illegal states for two encode method with endOfInput is true
+ public void testEncodeTrueIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+ // Normal case: just created
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ in.rewind();
+ out.rewind();
+
+ // Normal case: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ try {
+ encoder.encode(in, out, true);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.encode(in, out, true);
+ in.rewind();
+ out.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud905');
+ encoder.encode(in, out, true);
+ }
+
+ // test illegal states for two encode method with endOfInput is false
+ public void testEncodeFalseIllegalState() throws CharacterCodingException {
+ CharBuffer in = CharBuffer.wrap("aaa");
+ ByteBuffer out = ByteBuffer.allocate(5);
+ // Normal case: just created
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after encode facade
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState1"));
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+
+ // Illegal state: just after flush
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ try {
+ encoder.encode(in, out, false);
+ fail("should illegal state");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: after canEncode
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.encode(in, out, false);
+ in.rewind();
+ out.rewind();
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode('\ud905');
+ encoder.encode(in, out, false);
+ }
+
+ // test illegal states for two canEncode methods
+ public void testCanEncodeIllegalState() throws CharacterCodingException {
+ // Normal case: just created
+ encoder.canEncode("\ud900\udc00");
+ encoder.canEncode('\ud900');
+
+ // Illegal state: just after encode with that endOfInput is true
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState2"),
+ ByteBuffer.allocate(30), true);
+ try {
+ encoder.canEncode("\ud903\udc00");
+ fail("should throw illegal state exception");
+ } catch (IllegalStateException e) {
+ }
+
+ // Illegal state:just after encode with that endOfInput is false
+ assertSame(encoder, encoder.reset());
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState3"),
+ ByteBuffer.allocate(30), false);
+ try {
+ encoder.canEncode("\ud904\udc00");
+ fail("should throw illegal state exception");
+ } catch (IllegalStateException e) {
+ }
+
+ // Normal case: just after flush
+ encoder.encode(CharBuffer.wrap("testCanEncodeIllegalState4"),
+ ByteBuffer.allocate(30), true);
+ encoder.flush(ByteBuffer.allocate(10));
+ encoder.canEncode("\ud905\udc00");
+ encoder.canEncode('\ud906');
+
+ // Normal case: after reset again
+ assertSame(encoder, encoder.reset());
+ encoder.canEncode("\ud906\udc00");
+ encoder.canEncode('\ud905');
+ }
+
+ /*
+ * --------------------------------- illegal state test end
+ * ---------------------------------
+ */
+
+ /*
+ * Class under test for boolean canEncode(CharSequence)
+ */
+ public void testCanEncodeCharSequence() {
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void test_canEncode_char_ICUBug() {
+ // The RI doesn't allow this, but icu4c does.
+ assertTrue(encoder.canEncode('\ud800'));
+ }
+
+ public void test_canEncode_CharSequence_ICUBug() {
+ // The RI doesn't allow this, but icu4c does.
+ assertTrue(encoder.canEncode("\ud800"));
+ }
+
+ public void test_canEncode_empty() throws Exception {
+ assertTrue(encoder.canEncode(""));
+ }
+
+ public void test_canEncode_null() throws Exception {
+ try {
+ encoder.canEncode(null);
+ fail();
+ } catch (NullPointerException e) {
+ }
+ }
+
+ /*
+ * Class under test for Charset charset()
+ */
+ public void testCharset() {
+ try {
+ encoder = new MockCharsetEncoder(Charset.forName("gbk"), 1,
+ MAX_BYTES);
+ // assertSame(encoder.charset(), Charset.forName("gbk"));
+ } catch (UnsupportedCharsetException e) {
+ System.err
+ .println("Don't support GBK encoding, ignore current test");
+ }
+ }
+
+ /*
+ * Class under test for ByteBuffer encode(CharBuffer)
+ */
+ public void testEncodeCharBuffer() throws CharacterCodingException {
+ // Null pointer
+ try {
+ encoder.encode(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // empty input buffer
+ ByteBuffer out = encoder.encode(CharBuffer.wrap(""));
+ assertEquals(out.position(), 0);
+ assertByteArray(out, new byte[0]);
+ // assertByteArray(out, surrogate);
+
+ // normal case
+ out = encoder.encode(CharBuffer.wrap(unistr));
+ assertEquals(out.position(), 0);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ // Regression test for harmony-3378
+ Charset cs = Charset.forName("UTF-8");
+ CharsetEncoder encoder = cs.newEncoder();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ encoder = encoder.replaceWith(new byte[] { (byte) 0xef, (byte) 0xbf,
+ (byte) 0xbd, });
+ CharBuffer in = CharBuffer.wrap("\ud800");
+ out = encoder.encode(in);
+ assertNotNull(out);
+ }
+
+ private byte[] addSurrogate(byte[] expected) {
+ if (surrogate.length > 0) {
+ byte[] temp = new byte[surrogate.length + expected.length];
+ System.arraycopy(surrogate, 0, temp, 0, surrogate.length);
+ System.arraycopy(expected, 0, temp, surrogate.length,
+ expected.length);
+ expected = temp;
+ }
+ return expected;
+ }
+
+ /**
+ * @return
+ */
+ protected byte[] getEmptyByteArray() {
+ return new byte[0];
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("malform buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return CharBuffer.wrap("unmap buffer");
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return CharBuffer.wrap("runtime buffer");
+ }
+
+ public void testEncodeCharBufferException() throws CharacterCodingException {
+ ByteBuffer out;
+ CharBuffer in;
+ // MalformedException:
+ in = getMalformedCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ try {
+ // regression test for Harmony-1379
+ encoder.encode(in);
+ fail("should throw MalformedInputException");
+ } catch (MalformedInputException e) {
+ }
+
+ encoder.reset();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ out = encoder.encode(in);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ encoder.reset();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ out = encoder.encode(in);
+ assertByteArray(out, addSurrogate(unibytesWithRep));
+ }
+
+ // Unmapped Exception:
+ in = getUnmapCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ try {
+ encoder.encode(in);
+ fail("should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException e) {
+ }
+
+ encoder.reset();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ out = encoder.encode(in);
+ assertByteArray(out, unibytes);
+
+ encoder.reset();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ out = encoder.encode(in);
+ assertByteArray(out, unibytesWithRep);
+ }
+
+ // RuntimeException
+ try {
+ encoder.encode(getExceptionCharBuffer());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ /*
+ * utility method, extract given bytebuffer to a string and compare with
+ * give string
+ */
+ void assertByteArray(ByteBuffer out, byte[] expected) {
+ out = out.duplicate();
+ if (out.position() != 0) {
+ out.flip();
+ }
+ byte[] ba = new byte[out.limit() - out.position()];
+ out.get(ba);
+ // byte[] ba = out.array();
+ assertTrue(Arrays.equals(ba, expected));
+ }
+
+ /*
+ * Class under test for CoderResult encode(CharBuffer, ByteBuffer, boolean)
+ */
+ public void testEncodeCharBufferByteBufferboolean()
+ throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(200);
+ CharBuffer in = CharBuffer.wrap(unistr);
+ // Null pointer
+ try {
+ encoder.encode(null, out, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+ try {
+ encoder.encode(in, null, true);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+
+ // normal case, one complete operation
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+ in.rewind();
+
+ encoder.flush(out);
+
+ // normal case, one complete operation, but call twice, first time set
+ // endOfInput to false
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out = ByteBuffer.allocate(200);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+
+ assertByteArray(out, addSurrogate(duplicateByteArray(unibytes, 3)));
+
+ // overflow
+ out = ByteBuffer.allocate(4);
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out.rewind();
+ assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 4);
+ assertEquals(out.position(), 4);
+ assertEquals(out.remaining(), 0);
+ assertEquals(out.capacity(), 4);
+ ByteBuffer temp = ByteBuffer.allocate(200);
+ out.flip();
+ temp.put(out);
+ out = temp;
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+
+ assertSame(encoder, encoder.reset());
+ in.rewind();
+ out = ByteBuffer.allocate(4);
+ assertSame(CoderResult.OVERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 4);
+ assertEquals(out.position(), 4);
+ assertEquals(out.remaining(), 0);
+ assertEquals(out.capacity(), 4);
+ temp = ByteBuffer.allocate(200);
+ out.flip();
+ temp.put(out);
+ out = temp;
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, false));
+ assertEquals(out.limit(), 200);
+ assertTrue(out.position() > 0);
+ assertTrue(out.remaining() > 0);
+ assertEquals(out.capacity(), 200);
+ assertByteArray(out, addSurrogate(unibytes));
+ }
+
+ void printByteBuffer(ByteBuffer buffer) {
+ System.out.println("print buffer");
+ if (buffer.position() != 0) {
+ buffer.flip();
+ }
+ byte[] ba = buffer.array();
+ for (int i = 0; i < ba.length; i++) {
+ System.out.println(Integer.toHexString(ba[i]));
+ }
+ }
+
+ public void testEncodeCharBufferByteBufferbooleanExceptionFalse()
+ throws CharacterCodingException {
+ implTestEncodeCharBufferByteBufferbooleanException(false);
+ }
+
+ public void testEncodeCharBufferByteBufferbooleanExceptionTrue()
+ throws CharacterCodingException {
+ implTestEncodeCharBufferByteBufferbooleanException(true);
+ }
+
+ private byte[] duplicateByteArray(byte[] ba, int times) {
+ byte[] result = new byte[ba.length * times];
+ for (int i = 0; i < times; i++) {
+ System.arraycopy(ba, 0, result, i * ba.length, ba.length);
+ }
+ return result;
+ }
+
+ protected void implTestEncodeCharBufferByteBufferbooleanException(
+ boolean endOfInput) throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(100);
+
+ // MalformedException:
+ CharBuffer in = getMalformedCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ CoderResult r = encoder.encode(in, out, endOfInput);
+ assertTrue(r.isMalformed());
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onMalformedInput(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+ } else {
+ System.out.println("Cannot find malformed char buffer for "
+ + cs.name());
+ }
+
+ // Unmapped Exception:
+ in = getUnmapCharBuffer();
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ if (in != null) {
+ encoder.reset();
+ out.clear();
+ assertTrue(encoder.encode(in, out, endOfInput).isUnmappable());
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytes);
+
+ encoder.reset();
+ out.clear();
+ in.rewind();
+ encoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ assertCodingErrorAction(endOfInput, out, in, unibytesWithRep);
+ } else {
+ System.out.println("Cannot find unmapped char buffer for "
+ + cs.name());
+ }
+
+ // RuntimeException
+ try {
+ encoder.encode(getExceptionCharBuffer());
+ fail("should throw runtime exception");
+ } catch (RuntimeException e) {
+ }
+ }
+
+ private void assertCodingErrorAction(boolean endOfInput, ByteBuffer out,
+ CharBuffer in, byte[] expect) {
+ if (endOfInput) {
+ assertByteArray(out, addSurrogate(expect));
+ } else {
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out,
+ endOfInput));
+ in.rewind();
+ assertSame(CoderResult.UNDERFLOW, encoder.encode(in, out, true));
+ assertByteArray(out, addSurrogate(duplicateByteArray(expect, 3)));
+ }
+ }
+
+ /*
+ * Class under test for CoderResult flush(ByteBuffer)
+ */
+ public void testFlush() throws CharacterCodingException {
+ ByteBuffer out = ByteBuffer.allocate(6);
+ CharBuffer in = CharBuffer.wrap("aaa");
+ assertEquals(in.remaining(), 3);
+
+ // by encode facade, so that internal state will be wrong
+ encoder.encode(CharBuffer.wrap("testFlush"), ByteBuffer.allocate(20),
+ true);
+ assertSame(CoderResult.UNDERFLOW, encoder
+ .flush(ByteBuffer.allocate(50)));
+ }
+
+ /*
+ * test isLegalReplacement(byte[])
+ */
+ public void test_isLegalReplacement_null() {
+ try {
+ encoder.isLegalReplacement(null);
+ fail("should throw null pointer exception");
+ } catch (NullPointerException e) {
+ }
+ }
+
+ public void test_isLegalReplacement_good() {
+ assertTrue(encoder.isLegalReplacement(specifiedReplacement));
+ }
+
+ public void test_isLegalReplacement_bad() {
+ assertTrue(encoder.isLegalReplacement(new byte[200]));
+ byte[] ba = getIllegalByteArray();
+ if (ba != null) {
+ assertFalse(encoder.isLegalReplacement(ba));
+ }
+ }
+
+ public void test_isLegalReplacement_empty_array() {
+ // ISO, ASC, GB, UTF8 encoder will throw exception in RI
+ // others will pass
+ assertTrue(encoder.isLegalReplacement(new byte[0]));
+ }
+
+ public void testOnMalformedInput() {
+ assertSame(CodingErrorAction.REPORT, encoder.malformedInputAction());
+ try {
+ encoder.onMalformedInput(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ encoder.onMalformedInput(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, encoder.malformedInputAction());
+ }
+
+ public void testOnUnmappableCharacter() {
+ assertSame(CodingErrorAction.REPORT, encoder
+ .unmappableCharacterAction());
+ try {
+ encoder.onUnmappableCharacter(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+ assertSame(CodingErrorAction.IGNORE, encoder
+ .unmappableCharacterAction());
+ }
+
+ public void testReplacement() {
+ try {
+ encoder.replaceWith(null);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ encoder.replaceWith(new byte[0]);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ encoder.replaceWith(new byte[100]);
+ fail("should throw null pointer exception");
+ } catch (IllegalArgumentException e) {
+ }
+
+ byte[] nr = getLegalByteArray();
+ assertSame(encoder, encoder.replaceWith(nr));
+ assertSame(nr, encoder.replacement());
+
+ nr = getIllegalByteArray();
+ try {
+ encoder.replaceWith(new byte[100]);
+ fail();
+ } catch (IllegalArgumentException e) {
+ }
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { 'a' };
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[155];
+ }
+
+ /*
+ * Mock subclass of CharsetEncoder For protected method test
+ */
+ public static class MockCharsetEncoder extends CharsetEncoder {
+
+ boolean flushed = false;
+
+ public boolean isFlushed() {
+ boolean result = flushed;
+ flushed = false;
+ return result;
+ }
+
+ public boolean isLegalReplacement(byte[] ba) {
+ if (ba.length == 155) {// specified magic number, return false
+ return false;
+ }
+ return super.isLegalReplacement(ba);
+ }
+
+ public MockCharsetEncoder(Charset cs, float aver, float max) {
+ super(cs, aver, max);
+ }
+
+ public MockCharsetEncoder(Charset cs, float aver, float max,
+ byte[] replacement) {
+ super(cs, aver, max, replacement);
+ }
+
+ protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
+ int inPosition = in.position();
+ char[] input = new char[in.remaining()];
+ in.get(input);
+ String result = new String(input);
+ if (result.startsWith("malform")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // in.position(0);
+ // set the error length
+ return CoderResult.malformedForLength("malform".length());
+ } else if (result.startsWith("unmap")) {
+ // reset the cursor to the error position
+ in.position(inPosition);
+ // in.position(0);
+ // set the error length
+ return CoderResult.unmappableForLength("unmap".length());
+ } else if (result.startsWith("runtime")) {
+ // reset the cursor to the error position
+ in.position(0);
+ // set the error length
+ throw new RuntimeException("runtime");
+ }
+ int inLeft = input.length;
+ int outLeft = out.remaining();
+ CoderResult r = CoderResult.UNDERFLOW;
+ int length = inLeft;
+ if (outLeft < inLeft) {
+ r = CoderResult.OVERFLOW;
+ length = outLeft;
+ in.position(inPosition + outLeft);
+ }
+ for (int i = 0; i < length; i++) {
+ out.put((byte) input[i]);
+ }
+ return r;
+ }
+
+ protected CoderResult implFlush(ByteBuffer out) {
+ CoderResult result = super.implFlush(out);
+ int length = 0;
+ if (out.remaining() >= 5) {
+ length = 5;
+ result = CoderResult.UNDERFLOW;
+ flushed = true;
+ // for (int i = 0; i < length; i++) {
+ // out.put((byte)'f');
+ // }
+ } else {
+ length = out.remaining();
+ result = CoderResult.OVERFLOW;
+ }
+ return result;
+ }
+
+ protected void implReplaceWith(byte[] ba) {
+ assertSame(ba, replacement());
+ }
+
+ }
+
+ /*
+ * mock charset for test encoder initialization
+ */
+ public static class MockCharset extends Charset {
+ protected MockCharset(String arg0, String[] arg1) {
+ super(arg0, arg1);
+ }
+
+ public boolean contains(Charset arg0) {
+ return false;
+ }
+
+ public CharsetDecoder newDecoder() {
+ return new CharsetDecoderTest.MockCharsetDecoder(this,
+ (float) AVER_BYTES, MAX_BYTES);
+ }
+
+ public CharsetEncoder newEncoder() {
+ return new MockCharsetEncoder(this, (float) AVER_BYTES, MAX_BYTES);
+ }
+ }
+
+}
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
new file mode 100644
index 0000000..b38728a
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetProviderTest.java
@@ -0,0 +1,406 @@
+/* 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
new file mode 100644
index 0000000..c658c48
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CharsetTest.java
@@ -0,0 +1,839 @@
+/* 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.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.nio.charset.UnsupportedCharsetException;
+import java.nio.charset.spi.CharsetProvider;
+import java.security.Permission;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.SortedMap;
+import java.util.Vector;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.Charset.
+ */
+public class CharsetTest extends TestCase {
+
+ static MockCharset charset1 = new MockCharset("mockCharset00",
+ new String[] { "mockCharset01", "mockCharset02" });
+
+ static MockCharset charset2 = new MockCharset("mockCharset10",
+ new String[] { "mockCharset11", "mockCharset12" });
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * 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"));
+ }
+
+ /*
+ * 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);
+ }
+ }
+
+ /**
+ * @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);
+ }
+ }
+
+ /*
+ * Mock charset class.
+ */
+ 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);
+ }
+ }
+
+ /*
+ * Another mock charset class.
+ */
+ 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;
+ }
+ }
+
+ /*
+ * Mock encoder.
+ */
+ 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;
+ }
+ }
+
+ /*
+ * Mock decoder.
+ */
+ 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;
+ }
+ }
+
+ /*
+ * Mock charset provider.
+ */
+ public static class MockCharsetProvider extends CharsetProvider {
+
+ 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 Iterator charsets() {
+ Vector v = new Vector();
+ v.add(new MockCharset("mockCharset00", new String[] {
+ "mockCharset01", "mockCharset02" }));
+ return v.iterator();
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
new file mode 100644
index 0000000..469fc98
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CoderResultTest.java
@@ -0,0 +1,265 @@
+/* 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.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.charset.CoderResult;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CoderResult.
+ */
+public class CoderResultTest extends TestCase {
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test the constant OVERFLOW and UNDERFLOW.
+ */
+ public void testConstants() throws Exception {
+ assertNotSame(CoderResult.OVERFLOW, CoderResult.UNDERFLOW);
+
+ assertNotNull(CoderResult.OVERFLOW);
+ assertFalse(CoderResult.OVERFLOW.isError());
+ assertFalse(CoderResult.OVERFLOW.isMalformed());
+ assertFalse(CoderResult.OVERFLOW.isUnderflow());
+ assertFalse(CoderResult.OVERFLOW.isUnmappable());
+ assertTrue(CoderResult.OVERFLOW.isOverflow());
+ assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+ try {
+ CoderResult.OVERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferOverflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.OVERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+
+ assertNotNull(CoderResult.UNDERFLOW);
+ assertFalse(CoderResult.UNDERFLOW.isError());
+ assertFalse(CoderResult.UNDERFLOW.isMalformed());
+ assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+ assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+ assertFalse(CoderResult.UNDERFLOW.isOverflow());
+ assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+ try {
+ CoderResult.UNDERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferUnderflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.UNDERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method isError().
+ *
+ */
+ public void testIsError() {
+ assertFalse(CoderResult.UNDERFLOW.isError());
+ assertFalse(CoderResult.OVERFLOW.isError());
+ assertTrue(CoderResult.malformedForLength(1).isError());
+ assertTrue(CoderResult.unmappableForLength(1).isError());
+ }
+
+ /**
+ * Test method isMalformed().
+ *
+ */
+ public void testIsMalformed() {
+ assertFalse(CoderResult.UNDERFLOW.isMalformed());
+ assertFalse(CoderResult.OVERFLOW.isMalformed());
+ assertTrue(CoderResult.malformedForLength(1).isMalformed());
+ assertFalse(CoderResult.unmappableForLength(1).isMalformed());
+ }
+
+ /**
+ * Test method isMalformed().
+ *
+ */
+ public void testIsUnmappable() {
+ assertFalse(CoderResult.UNDERFLOW.isUnmappable());
+ assertFalse(CoderResult.OVERFLOW.isUnmappable());
+ assertFalse(CoderResult.malformedForLength(1).isUnmappable());
+ assertTrue(CoderResult.unmappableForLength(1).isUnmappable());
+ }
+
+ /**
+ * Test method isOverflow().
+ *
+ */
+ public void testIsOverflow() {
+ assertFalse(CoderResult.UNDERFLOW.isOverflow());
+ assertTrue(CoderResult.OVERFLOW.isOverflow());
+ assertFalse(CoderResult.malformedForLength(1).isOverflow());
+ assertFalse(CoderResult.unmappableForLength(1).isOverflow());
+ }
+
+ /**
+ * Test method isUnderflow().
+ *
+ */
+ public void testIsUnderflow() {
+ assertTrue(CoderResult.UNDERFLOW.isUnderflow());
+ assertFalse(CoderResult.OVERFLOW.isUnderflow());
+ assertFalse(CoderResult.malformedForLength(1).isUnderflow());
+ assertFalse(CoderResult.unmappableForLength(1).isUnderflow());
+ }
+
+ /**
+ * Test method length().
+ *
+ */
+ public void testLength() {
+ try {
+ CoderResult.UNDERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+ try {
+ CoderResult.OVERFLOW.length();
+ fail("Should throw UnsupportedOperationException");
+ } catch (UnsupportedOperationException ex) {
+ // expected
+ }
+
+ assertEquals(CoderResult.malformedForLength(1).length(), 1);
+ assertEquals(CoderResult.unmappableForLength(1).length(), 1);
+ }
+
+ /**
+ * Test method malformedForLength(int).
+ *
+ */
+ public void testMalformedForLength() {
+ assertNotNull(CoderResult.malformedForLength(Integer.MAX_VALUE));
+ assertNotNull(CoderResult.malformedForLength(1));
+ assertSame(CoderResult.malformedForLength(1), CoderResult
+ .malformedForLength(1));
+ assertNotSame(CoderResult.malformedForLength(1), CoderResult
+ .unmappableForLength(1));
+ assertNotSame(CoderResult.malformedForLength(2), CoderResult
+ .malformedForLength(1));
+ try {
+ CoderResult.malformedForLength(-1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ CoderResult.malformedForLength(0);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method unmappableForLength(int).
+ *
+ */
+ public void testUnmappableForLength() {
+ assertNotNull(CoderResult.unmappableForLength(Integer.MAX_VALUE));
+ assertNotNull(CoderResult.unmappableForLength(1));
+ assertSame(CoderResult.unmappableForLength(1), CoderResult
+ .unmappableForLength(1));
+ assertNotSame(CoderResult.unmappableForLength(2), CoderResult
+ .unmappableForLength(1));
+ try {
+ CoderResult.unmappableForLength(-1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ try {
+ CoderResult.unmappableForLength(0);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * Test method throwException().
+ *
+ */
+ public void testThrowException() throws Exception {
+ try {
+ CoderResult.OVERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferOverflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.UNDERFLOW.throwException();
+ fail("Should throw BufferOverflowException");
+ } catch (BufferUnderflowException ex) {
+ // expected
+ }
+ try {
+ CoderResult.malformedForLength(1).throwException();
+ fail("Should throw MalformedInputException");
+ } catch (MalformedInputException ex) {
+ assertEquals(ex.getInputLength(), 1);
+ }
+ try {
+ CoderResult.unmappableForLength(1).throwException();
+ fail("Should throw UnmappableCharacterException");
+ } catch (UnmappableCharacterException ex) {
+ assertEquals(ex.getInputLength(), 1);
+ }
+ }
+
+ /**
+ * Test method toString().
+ *
+ */
+ public void testToString() throws Exception {
+ assertTrue(CoderResult.OVERFLOW.toString().indexOf("OVERFLOW") != -1);
+ assertTrue(CoderResult.UNDERFLOW.toString().indexOf("UNDERFLOW") != -1);
+ assertTrue(CoderResult.malformedForLength(666).toString()
+ .indexOf("666") != -1);
+ assertTrue(CoderResult.unmappableForLength(666).toString().indexOf(
+ "666") != -1);
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
new file mode 100644
index 0000000..da293bb
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/CodingErrorActionTest.java
@@ -0,0 +1,62 @@
+/* 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.nio.charset.CodingErrorAction;
+
+import junit.framework.TestCase;
+
+/**
+ * Test class java.nio.charset.CodingErrorAction
+ */
+public class CodingErrorActionTest extends TestCase {
+
+ /*
+ * @see TestCase#setUp()
+ */
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /*
+ * @see TestCase#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /*
+ * Test the constants.
+ */
+ public void testIGNORE() {
+ assertNotNull(CodingErrorAction.IGNORE);
+ assertNotNull(CodingErrorAction.REPLACE);
+ assertNotNull(CodingErrorAction.REPORT);
+ assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPLACE);
+ assertNotSame(CodingErrorAction.IGNORE, CodingErrorAction.REPORT);
+ assertNotSame(CodingErrorAction.REPLACE, CodingErrorAction.REPORT);
+ }
+
+ /*
+ * Test the method toString().
+ */
+ public void testToString() {
+ assertTrue(CodingErrorAction.IGNORE.toString().indexOf("IGNORE") != -1);
+ assertTrue(CodingErrorAction.REPLACE.toString().indexOf("REPLACE") != -1);
+ assertTrue(CodingErrorAction.REPORT.toString().indexOf("REPORT") != -1);
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
new file mode 100644
index 0000000..e129c54
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetDecoderTest.java
@@ -0,0 +1,64 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test gb18030 decoder
+ */
+public class GBCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("gb18030");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // //assertEquals(1, decoder.averageCharsPerByte());
+ // //assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.25, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ ByteBuffer buffer = ByteBuffer.allocate(20);
+ buffer.put(new byte[] { (byte) 0xd8 });
+ buffer.put(getByteBuffer());
+ buffer.flip();
+ return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
new file mode 100644
index 0000000..ab4eeea
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/GBCharsetEncoderTest.java
@@ -0,0 +1,89 @@
+/* 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.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of gb18030 charset encoder
+ */
+public class GBCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for gb180303
+ private static final Charset CS = Charset.forName("gb18030");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { 0x1a };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCanEncodechar() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ /*
+ * Class under test for boolean canEncode(CharSequence)
+ */
+ public void testCanEncodeCharSequence() {
+ // surrogate char
+
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(4.0, encoder.maxBytesPerChar(), 0.0);
+ assertEquals(2.5, encoder.averageBytesPerChar(), 0.0);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte) 0xd8, (byte) 0x00 };
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
new file mode 100644
index 0000000..82ba9b3
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetDecoderTest.java
@@ -0,0 +1,61 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test ISO-8859-1 decoder
+ */
+public class ISOCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("iso-8859-1");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // assertEquals(1, decoder.averageCharsPerByte());
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // TODO how on map?
+ return null;
+
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ // TODO how malform
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
new file mode 100644
index 0000000..8a84938
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetEncoderTest.java
@@ -0,0 +1,93 @@
+/* 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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.MalformedInputException;
+import java.nio.charset.UnmappableCharacterException;
+
+/**
+ * test case specific activity of iso-8859-1 charset encoder
+ */
+public class ISOCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for iso-8859-1
+ private static final Charset CS = Charset.forName("iso-8859-1");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override public void testCanEncodeCharSequence() {
+ // normal case for isoCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertFalse(encoder.canEncode("\uc2a3"));
+ assertFalse(encoder.canEncode("\ud800\udc00"));
+ }
+
+ @Override public void testCanEncodechar() throws CharacterCodingException {
+ assertTrue(encoder.canEncode('\u0077'));
+ assertFalse(encoder.canEncode('\uc2a3'));
+ }
+
+ @Override public void testSpecificDefaultValue() {
+ assertEquals(1, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(1, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return CharBuffer.wrap("\ud800\udc00 buffer");
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return null;
+ }
+
+ public void testMultiStepEncode() throws CharacterCodingException {
+ encoder.onMalformedInput(CodingErrorAction.REPORT);
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ try {
+ encoder.encode(CharBuffer.wrap("\ud800\udc00"));
+ fail("should unmappable");
+ } catch (UnmappableCharacterException e) {
+ }
+ encoder.reset();
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
new file mode 100644
index 0000000..689dbf3
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/ISOCharsetTest.java
@@ -0,0 +1,58 @@
+/* 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;
+
+/**
+ * Test ISO-8859-1.
+ */
+public class ISOCharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public ISOCharsetTest(String arg0) {
+ super(arg0, "ISO-8859-1", new String[] { "iso-ir-100", "8859_1",
+ "ISO_8859-1", "ISO8859_1", "819", "csISOLatin1", "IBM-819",
+ "ISO_8859-1:1987", "latin1", "cp819", "ISO8859-1", "IBM819",
+ "ISO_8859_1", "l1" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98,
+ this.testingCharset.newEncoder().replacement()[0],
+ this.testingCharset.newEncoder().replacement()[0] };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, 63, 63 };
+ char[] output = "ab??".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
new file mode 100644
index 0000000..a8e1343
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ *
+ */
+public class UTF16BECharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16be");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte() {
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // no unmap byte buffer
+ return null;
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here, RI can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte)0xd8);
+ // buffer.put((byte)0xd8);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ protected ByteBuffer getByteBuffer() {
+ return ByteBuffer.wrap(new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0,
+ 102, 0, 101, 0, 114 });
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
new file mode 100644
index 0000000..68bd2f5
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetEncoderTest.java
@@ -0,0 +1,108 @@
+/* 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.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16BECharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16be
+ private static final Charset CS = Charset.forName("utf-16be");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -1, -3 };
+ unibytes = new byte[] { 0, 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101,
+ 0, 114 };
+
+ // unibytesWithRep = new byte[] {(byte)0xff, (byte)0xfd,0, 32, 0, 98, 0,
+ // 117, 0, 102, 0, 102, 0, 101, 0, 114};
+
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte)0xd8, (byte)0x00, (byte)0xdb, (byte)0x00 };
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { (byte) 0x00, (byte) 0xd8 };
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
new file mode 100644
index 0000000..52cee90
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16BECharsetTest.java
@@ -0,0 +1,53 @@
+/* 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;
+
+/**
+ * Test UTF-16BE.
+ */
+public class UTF16BECharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16BECharsetTest(String arg0) {
+ super(arg0, "UTF-16BE", new String[] { "X-UTF-16BE", "UTF_16BE" },
+ true, true); // "ISO-10646-UCS-2"
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 0, 97, 0, 98, 93, 20, 101, 79 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
new file mode 100644
index 0000000..c5bb408
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetDecoderTest.java
@@ -0,0 +1,118 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CoderResult;
+import java.nio.charset.CodingErrorAction;
+
+/**
+ *
+ */
+public class UTF16CharsetDecoderTest extends CharsetDecoderTest {
+
+ boolean bigEndian = true;
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16");
+ bom = "\ufeff";
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ protected ByteBuffer getByteBuffer() {
+ // FIXME: different here
+ // if don't specified BOM
+ // ICU default is LE
+ // JDK default is BE
+
+ // maybe start with 0xFEFF, which means big endian
+ // 0xFFFE, which means little endian
+ byte[] b = (bigEndian) ? new byte[] { -1, -2, 32, 0, 98, 0, 117, 0,
+ 102, 0, 102, 0, 101, 0, 114, 0 } : new byte[] { -2, -1, 0, 32,
+ 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0, 114 };
+ return ByteBuffer.wrap(b);
+ }
+
+ protected ByteBuffer getHeadlessByteBuffer() {
+ ByteBuffer b = getByteBuffer();
+ b.position(2);
+ byte[] bytes = new byte[b.remaining()];
+ b.get(bytes);
+ return ByteBuffer.wrap(bytes);
+ }
+
+ public void testLittleEndianByteBufferCharBuffer()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ bigEndian = false;
+ implTestDecodeByteBufferCharBuffer(getByteBuffer());
+ bigEndian = true;
+ }
+
+ public void testLittleEndianReadOnlyByteBufferCharBuffer()
+ throws CharacterCodingException, UnsupportedEncodingException {
+ bigEndian = false;
+ implTestDecodeByteBufferCharBuffer(getByteBuffer().asReadOnlyBuffer());
+ bigEndian = true;
+ }
+
+ public void testLittleEndian() throws CharacterCodingException,
+ UnsupportedEncodingException {
+ bigEndian = false;
+ implTestDecodeByteBuffer();
+ bigEndian = true;
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte() {
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ // FIXME: different here, RI can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte) -1);
+ // buffer.put((byte) -2);
+ // buffer.put((byte) 0xdc);
+ // buffer.put((byte) 0xdc);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
new file mode 100644
index 0000000..6a42d41
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetEncoderTest.java
@@ -0,0 +1,128 @@
+/* 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.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+/**
+ * TODO type def
+ */
+public class UTF16CharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16
+ // charset for utf-16be
+ private static final Charset CS = Charset.forName("utf-16");
+
+ private static final CharsetDecoder decoder = CS.newDecoder();
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -3, -1 };
+ surrogate = new byte[] { -1, -2 };
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+ unibytesWithRep = new byte[] { -3, -1, 32, 0, 98, 0, 117, 0, 102, 0,
+ 102, 0, 101, 0, 114, 0 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(encoder.averageBytesPerChar(), 2, 0.001);
+ // assertEquals(4, encoder.maxBytesPerChar());
+ // FIXME: different here!
+ assertEquals(encoder.maxBytesPerChar(), 2, 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte)0xd8, (byte)0x00, (byte)0xdb, (byte)0x00 };
+ }
+
+ protected byte[] getLegalByteArray() {
+ // FIXME: Different Here!
+ // return new byte[]{(byte)0xd8, 0x00};
+ return new byte[] { (byte) 0x00, (byte) 0xd8 };
+ }
+
+ void assertByteArray(ByteBuffer out, byte[] expected) {
+ out = out.duplicate();
+ if (out.position() > 0) {
+ out.flip();
+ }
+ try {
+ assertEquals(decoder.decode(out), decoder.decode(ByteBuffer
+ .wrap(expected)));
+ } catch (CharacterCodingException e) {
+ fail(e.toString());
+ }
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
new file mode 100644
index 0000000..61dcf49
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16CharsetTest.java
@@ -0,0 +1,51 @@
+/* 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;
+
+/**
+ * Test UTF-16.
+ */
+public class UTF16CharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16CharsetTest(String arg0) {
+ super(arg0, "UTF-16", new String[] { "UTF_16" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
new file mode 100644
index 0000000..e9a8e56
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetDecoderTest.java
@@ -0,0 +1,72 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * TODO typedef
+ */
+public class UTF16LECharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-16le");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // assertEquals(decoder.averageCharsPerByte(), 0.5, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ // no unmap byte buffer
+ return null;
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ // FIXME: different here, JDK can parse 0xd8d8
+ // ByteBuffer buffer = ByteBuffer.allocate(100);
+ // buffer.put((byte)0xd8);
+ // buffer.put((byte)0xd8);
+ // buffer.put(unibytes);
+ // buffer.flip();
+ // return buffer;
+ return null;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ protected ByteBuffer getByteBuffer() {
+ return ByteBuffer.wrap(new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102,
+ 0, 101, 0, 114, 0 });
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
new file mode 100644
index 0000000..1e9187d
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetEncoderTest.java
@@ -0,0 +1,109 @@
+/* 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.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * TODO type def
+ */
+public class UTF16LECharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for utf-16le
+ private static final Charset CS = Charset.forName("utf-16le");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { -3, -1 };
+
+ unibytes = new byte[] { 32, 0, 98, 0, 117, 0, 102, 0, 102, 0, 101, 0,
+ 114, 0 };
+
+ // unibytesWithRep = new byte[] {(byte)0xfd, (byte)0xff, 32, 0, 98, 0,
+ // 117, 0, 102, 0, 102, 0, 101, 0, 114 ,0};
+
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCharsetEncoderCharsetfloatfloat() {
+ // this constructor is invalid for UTF16LE CharsetEncoder
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ public void testSpecificDefaultValue() {
+ assertEquals(2, encoder.averageBytesPerChar(), 0.001);
+ assertEquals(2, encoder.maxBytesPerChar(), 0.001);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte)0x00, (byte)0xd8, (byte)0x00, (byte)0xdb };
+ }
+
+ protected byte[] getLegalByteArray() {
+ return new byte[] { (byte) 0xd8, 0x00 };
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
new file mode 100644
index 0000000..d795773
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF16LECharsetTest.java
@@ -0,0 +1,54 @@
+/* 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;
+
+/**
+ * Test UTF-16LE.
+ */
+public class UTF16LECharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor.
+ */
+ public UTF16LECharsetTest(String arg0) {
+ super(arg0, "UTF-16LE", new String[] { "UTF_16LE", "X-UTF-16LE" },
+ true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+ internalTestEncode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 0, 98, 0, 20, 93, 79, 101 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
new file mode 100644
index 0000000..8ab8b5c
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTF8CharsetTest.java
@@ -0,0 +1,62 @@
+/* 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.UnsupportedEncodingException;
+
+/**
+ * Test UTF-8 charset.
+ */
+public class UTF8CharsetTest extends AbstractCharsetTestCase {
+
+ /**
+ * Constructor for UTF8CharsetTest.
+ *
+ */
+ public UTF8CharsetTest(String arg0) {
+ super(arg0, "UTF-8", new String[] { "UTF8" }, true, true);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testDecode_Normal()
+ */
+ public void testDecode_Normal() {
+ byte[] input = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+ char[] output = "ab\u5D14\u654F".toCharArray();
+ internalTestDecode(input, output);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see tests.api.java.nio.charset.ConcreteCharsetTest#testEncode_Normal()
+ */
+ public void testEncode_Normal() {
+ String input = "ab\u5D14\u654F";
+ byte[] output = new byte[] { 97, 98, -27, -76, -108, -26, -107, -113 };
+ internalTestEncode(input, output);
+ }
+
+ public void test_surrogate() throws UnsupportedEncodingException {
+ // U+1D11E: MUSICAL SYMBOL G CLEF
+ String s = new StringBuilder().appendCodePoint(0x1D11E).toString();
+ byte utf8[] = s.getBytes("UTF-8");
+ assertEquals(s, new String(utf8, 0, utf8.length, "UTF-8"));
+ }
+}
diff --git a/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
new file mode 100644
index 0000000..b8ed9fd
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetDecoderTest.java
@@ -0,0 +1,76 @@
+/* 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.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+
+/**
+ * test utf-8 decoder
+ */
+public class UTFCharsetDecoderTest extends CharsetDecoderTest {
+
+ protected void setUp() throws Exception {
+ cs = Charset.forName("utf-8");
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetDecoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ // FIXME: give up this tests
+ // public void testDefaultCharsPerByte(){
+ // assertEquals(decoder.averageCharsPerByte(), 0.333, 0.001);
+ // assertEquals(decoder.maxCharsPerByte(), 2, 0.001);
+ // // assertEquals(1, decoder.averageCharsPerByte());
+ // // assertEquals(1, decoder.maxCharsPerByte());
+ // }
+
+ ByteBuffer getUnmappedByteBuffer() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ ByteBuffer getMalformedByteBuffer() throws UnsupportedEncodingException {
+ ByteBuffer buffer = ByteBuffer.allocate(getByteBuffer().remaining() + 1);
+ buffer.put((byte) 0xd8);
+ buffer.put(getByteBuffer());
+ buffer.flip();
+ return buffer;
+ }
+
+ ByteBuffer getExceptionByteArray() throws UnsupportedEncodingException {
+ return null;
+ }
+
+ protected String getString() {
+ return " buffer \u041c\u0430\u0441\u044e\u043b\u044f \u611b";
+ }
+
+ protected ByteBuffer getByteBuffer() {
+ return ByteBuffer.wrap(new byte[] { 32, 98, 117, 102, 102, 101, 114,
+ 32, (byte) 0xd0, (byte) 0x9c, (byte) 0xd0, (byte) 0xb0,
+ (byte) 0xd1, (byte) 0x81, (byte) 0xd1, (byte) 0x8e,
+ (byte) 0xd0, (byte) 0xbb, (byte) 0xd1, (byte) 0x8f, 32,
+ (byte) 0xe6, (byte) 0x84, (byte) 0x9b });
+ }
+
+}
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
new file mode 100644
index 0000000..798a048
--- /dev/null
+++ b/harmony-tests/src/test/java/tests/api/java/nio/charset/UTFCharsetEncoderTest.java
@@ -0,0 +1,98 @@
+/* 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.nio.CharBuffer;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+
+/**
+ * test case specific activity of utf-8 charset encoder
+ */
+public class UTFCharsetEncoderTest extends CharsetEncoderTest {
+
+ // charset for UTF-8
+ private static final Charset CS = Charset.forName("utf-8");
+
+ /*
+ * @see CharsetEncoderTest#setUp()
+ */
+ protected void setUp() throws Exception {
+ cs = CS;
+ specifiedReplacement = new byte[] { 63 };
+ super.setUp();
+ }
+
+ /*
+ * @see CharsetEncoderTest#tearDown()
+ */
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public void testCanEncodechar() throws CharacterCodingException {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode('\u0077'));
+ assertTrue(encoder.canEncode('\uc2a3'));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode('\uc2c0'));
+ }
+
+ public void testCanEncodeCharSequence() {
+ // normal case for utfCS
+ assertTrue(encoder.canEncode("\u0077"));
+ assertTrue(encoder.canEncode("\uc2a3"));
+
+ // for non-mapped char
+ assertTrue(encoder.canEncode("\uc2c0"));
+
+ // surrogate char for unicode
+ // 1st byte: d800-dbff
+ // 2nd byte: dc00-dfff
+ // valid surrogate pair
+ assertTrue(encoder.canEncode("\ud800\udc00"));
+ // invalid surrogate pair
+ assertFalse(encoder.canEncode("\ud800\udb00"));
+ }
+
+ 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);
+ }
+
+ CharBuffer getMalformedCharBuffer() {
+ return CharBuffer.wrap("\ud800 buffer");
+ }
+
+ CharBuffer getUnmapCharBuffer() {
+ return null;
+ }
+
+ CharBuffer getExceptionCharBuffer() {
+ return null;
+ }
+
+ protected byte[] getIllegalByteArray() {
+ return new byte[] { (byte) 0xd8, (byte) 0x00 };
+ }
+
+ protected void assertFlushed() {
+ }
+}
diff --git a/include/ScopedBytes.h b/include/ScopedBytes.h
deleted file mode 100644
index cb2614b..0000000
--- a/include/ScopedBytes.h
+++ /dev/null
@@ -1,80 +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.
- */
-
-#ifndef SCOPED_BYTES_H_included
-#define SCOPED_BYTES_H_included
-
-#include "JNIHelp.h"
-
-/**
- * ScopedBytesRO and ScopedBytesRW attempt to paper over the differences between byte[]s and
- * ByteBuffers. This in turn helps paper over the differences between non-direct ByteBuffers backed
- * by byte[]s, direct ByteBuffers backed by bytes[]s, and direct ByteBuffers not backed by byte[]s.
- * (On Android, this last group only contains MappedByteBuffers.)
- */
-template<bool readOnly>
-class ScopedBytes {
-public:
- ScopedBytes(JNIEnv* env, jobject object)
- : mEnv(env), mObject(object), mByteArray(NULL), mPtr(NULL)
- {
- if (mObject == NULL) {
- jniThrowNullPointerException(mEnv, NULL);
- } else if (mEnv->IsInstanceOf(mObject, JniConstants::byteArrayClass)) {
- mByteArray = reinterpret_cast<jbyteArray>(mObject);
- mPtr = mEnv->GetByteArrayElements(mByteArray, NULL);
- } else {
- mPtr = reinterpret_cast<jbyte*>(mEnv->GetDirectBufferAddress(mObject));
- }
- }
-
- ~ScopedBytes() {
- if (mByteArray != NULL) {
- mEnv->ReleaseByteArrayElements(mByteArray, mPtr, readOnly ? JNI_ABORT : 0);
- }
- }
-
-private:
- JNIEnv* mEnv;
- jobject mObject;
- jbyteArray mByteArray;
-
-protected:
- jbyte* mPtr;
-
-private:
- // Disallow copy and assignment.
- ScopedBytes(const ScopedBytes&);
- void operator=(const ScopedBytes&);
-};
-
-class ScopedBytesRO : public ScopedBytes<true> {
-public:
- ScopedBytesRO(JNIEnv* env, jobject object) : ScopedBytes<true>(env, object) {}
- const jbyte* get() const {
- return mPtr;
- }
-};
-
-class ScopedBytesRW : public ScopedBytes<false> {
-public:
- ScopedBytesRW(JNIEnv* env, jobject object) : ScopedBytes<false>(env, object) {}
- jbyte* get() {
- return mPtr;
- }
-};
-
-#endif // SCOPED_BYTES_H_included
diff --git a/include/ScopedFd.h b/include/ScopedFd.h
deleted file mode 100644
index d2b7935..0000000
--- a/include/ScopedFd.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef SCOPED_FD_H_included
-#define SCOPED_FD_H_included
-
-#include <unistd.h>
-
-// A smart pointer that closes the given fd on going out of scope.
-// Use this when the fd is incidental to the purpose of your function,
-// but needs to be cleaned up on exit.
-class ScopedFd {
-public:
- explicit ScopedFd(int fd) : fd(fd) {
- }
-
- ~ScopedFd() {
- close(fd);
- }
-
- int get() const {
- return fd;
- }
-
-private:
- int fd;
-
- // Disallow copy and assignment.
- ScopedFd(const ScopedFd&);
- void operator=(const ScopedFd&);
-};
-
-#endif // SCOPED_FD_H_included
diff --git a/include/ScopedLocalFrame.h b/include/ScopedLocalFrame.h
deleted file mode 100644
index 35b6ad8..0000000
--- a/include/ScopedLocalFrame.h
+++ /dev/null
@@ -1,40 +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.
- */
-
-#ifndef SCOPED_LOCAL_FRAME_H_included
-#define SCOPED_LOCAL_FRAME_H_included
-
-#include "JNIHelp.h"
-
-class ScopedLocalFrame {
-public:
- ScopedLocalFrame(JNIEnv* env) : mEnv(env) {
- mEnv->PushLocalFrame(128);
- }
-
- ~ScopedLocalFrame() {
- mEnv->PopLocalFrame(NULL);
- }
-
-private:
- JNIEnv* mEnv;
-
- // Disallow copy and assignment.
- ScopedLocalFrame(const ScopedLocalFrame&);
- void operator=(const ScopedLocalFrame&);
-};
-
-#endif // SCOPED_LOCAL_FRAME_H_included
diff --git a/include/ScopedLocalRef.h b/include/ScopedLocalRef.h
deleted file mode 100644
index 71d5776..0000000
--- a/include/ScopedLocalRef.h
+++ /dev/null
@@ -1,63 +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.
- */
-
-#ifndef SCOPED_LOCAL_REF_H_included
-#define SCOPED_LOCAL_REF_H_included
-
-#include "jni.h"
-
-#include <stddef.h>
-
-// A smart pointer that deletes a JNI local reference when it goes out of scope.
-template<typename T>
-class ScopedLocalRef {
-public:
- ScopedLocalRef(JNIEnv* env, T localRef) : mEnv(env), mLocalRef(localRef) {
- }
-
- ~ScopedLocalRef() {
- reset();
- }
-
- void reset(T ptr = NULL) {
- if (ptr != mLocalRef) {
- if (mLocalRef != NULL) {
- mEnv->DeleteLocalRef(mLocalRef);
- }
- mLocalRef = ptr;
- }
- }
-
- T release() __attribute__((warn_unused_result)) {
- T localRef = mLocalRef;
- mLocalRef = NULL;
- return localRef;
- }
-
- T get() const {
- return mLocalRef;
- }
-
-private:
- JNIEnv* mEnv;
- T mLocalRef;
-
- // Disallow copy and assignment.
- ScopedLocalRef(const ScopedLocalRef&);
- void operator=(const ScopedLocalRef&);
-};
-
-#endif // SCOPED_LOCAL_REF_H_included
diff --git a/include/ScopedPrimitiveArray.h b/include/ScopedPrimitiveArray.h
deleted file mode 100644
index f6626b2..0000000
--- a/include/ScopedPrimitiveArray.h
+++ /dev/null
@@ -1,110 +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.
- */
-
-#ifndef SCOPED_PRIMITIVE_ARRAY_H_included
-#define SCOPED_PRIMITIVE_ARRAY_H_included
-
-#include "JNIHelp.h"
-
-// ScopedBooleanArrayRO, ScopedByteArrayRO, ScopedCharArrayRO, ScopedDoubleArrayRO,
-// ScopedFloatArrayRO, ScopedIntArrayRO, ScopedLongArrayRO, and ScopedShortArrayRO provide
-// convenient read-only access to Java arrays from JNI code. This is cheaper than read-write
-// access and should be used by default.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(PRIMITIVE_TYPE, NAME) \
- class Scoped ## NAME ## ArrayRO { \
- public: \
- Scoped ## NAME ## ArrayRO(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
- : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
- if (mJavaArray == NULL) { \
- jniThrowNullPointerException(mEnv, NULL); \
- } else { \
- mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
- } \
- } \
- ~Scoped ## NAME ## ArrayRO() { \
- if (mRawArray) { \
- mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, JNI_ABORT); \
- } \
- } \
- const PRIMITIVE_TYPE* get() const { return mRawArray; } \
- PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
- const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
- size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
- private: \
- JNIEnv* mEnv; \
- PRIMITIVE_TYPE ## Array mJavaArray; \
- PRIMITIVE_TYPE* mRawArray; \
- Scoped ## NAME ## ArrayRO(const Scoped ## NAME ## ArrayRO&); \
- void operator=(const Scoped ## NAME ## ArrayRO&); \
- }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RO
-
-// ScopedBooleanArrayRW, ScopedByteArrayRW, ScopedCharArrayRW, ScopedDoubleArrayRW,
-// ScopedFloatArrayRW, ScopedIntArrayRW, ScopedLongArrayRW, and ScopedShortArrayRW provide
-// convenient read-write access to Java arrays from JNI code. These are more expensive,
-// since they entail a copy back onto the Java heap, and should only be used when necessary.
-#define INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(PRIMITIVE_TYPE, NAME) \
- class Scoped ## NAME ## ArrayRW { \
- public: \
- Scoped ## NAME ## ArrayRW(JNIEnv* env, PRIMITIVE_TYPE ## Array javaArray) \
- : mEnv(env), mJavaArray(javaArray), mRawArray(NULL) { \
- if (mJavaArray == NULL) { \
- jniThrowNullPointerException(mEnv, NULL); \
- } else { \
- mRawArray = mEnv->Get ## NAME ## ArrayElements(mJavaArray, NULL); \
- } \
- } \
- ~Scoped ## NAME ## ArrayRW() { \
- if (mRawArray) { \
- mEnv->Release ## NAME ## ArrayElements(mJavaArray, mRawArray, 0); \
- } \
- } \
- const PRIMITIVE_TYPE* get() const { return mRawArray; } \
- PRIMITIVE_TYPE ## Array getJavaArray() const { return mJavaArray; } \
- const PRIMITIVE_TYPE& operator[](size_t n) const { return mRawArray[n]; } \
- PRIMITIVE_TYPE* get() { return mRawArray; } \
- PRIMITIVE_TYPE& operator[](size_t n) { return mRawArray[n]; } \
- size_t size() const { return mEnv->GetArrayLength(mJavaArray); } \
- private: \
- JNIEnv* mEnv; \
- PRIMITIVE_TYPE ## Array mJavaArray; \
- PRIMITIVE_TYPE* mRawArray; \
- Scoped ## NAME ## ArrayRW(const Scoped ## NAME ## ArrayRW&); \
- void operator=(const Scoped ## NAME ## ArrayRW&); \
- }
-
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jboolean, Boolean);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jbyte, Byte);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jchar, Char);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jdouble, Double);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jfloat, Float);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jint, Int);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jlong, Long);
-INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW(jshort, Short);
-
-#undef INSTANTIATE_SCOPED_PRIMITIVE_ARRAY_RW
-
-#endif // SCOPED_PRIMITIVE_ARRAY_H_included
diff --git a/include/ScopedStringChars.h b/include/ScopedStringChars.h
deleted file mode 100644
index b59b786..0000000
--- a/include/ScopedStringChars.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef SCOPED_STRING_CHARS_H_included
-#define SCOPED_STRING_CHARS_H_included
-
-#include "JNIHelp.h"
-
-// A smart pointer that provides access to a jchar* given a JNI jstring.
-class ScopedStringChars {
-public:
- ScopedStringChars(JNIEnv* env, jstring s) : mEnv(env), mString(s), mSize(0) {
- mChars = env->GetStringChars(mString, NULL);
- if (mChars != NULL) {
- mSize = env->GetStringLength(mString);
- }
- }
-
- ~ScopedStringChars() {
- mEnv->ReleaseStringChars(mString, mChars);
- }
-
- const jchar* get() const { return mChars; }
- const jchar& operator[](size_t n) const { return mChars[n]; }
- size_t size() const { return mSize; }
-
-private:
- JNIEnv* mEnv;
- jstring mString;
- const jchar* mChars;
- size_t mSize;
-
- // Disallow copy and assignment.
- ScopedStringChars(const ScopedStringChars&);
- void operator=(const ScopedStringChars&);
-};
-
-#endif // SCOPED_STRING_CHARS_H_included
diff --git a/include/ScopedUtfChars.h b/include/ScopedUtfChars.h
deleted file mode 100644
index 7492a0c..0000000
--- a/include/ScopedUtfChars.h
+++ /dev/null
@@ -1,74 +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.
- */
-
-#ifndef SCOPED_UTF_CHARS_H_included
-#define SCOPED_UTF_CHARS_H_included
-
-#include "JNIHelp.h"
-#include <string.h>
-
-// A smart pointer that provides read-only access to a Java string's UTF chars.
-// Unlike GetStringUTFChars, we throw NullPointerException rather than abort if
-// passed a null jstring, and c_str will return NULL.
-// This makes the correct idiom very simple:
-//
-// ScopedUtfChars name(env, javaName);
-// if (name.c_str() == NULL) {
-// return NULL;
-// }
-class ScopedUtfChars {
-public:
- ScopedUtfChars(JNIEnv* env, jstring s)
- : mEnv(env), mString(s)
- {
- if (s == NULL) {
- mUtfChars = NULL;
- jniThrowNullPointerException(env, NULL);
- } else {
- mUtfChars = env->GetStringUTFChars(s, NULL);
- }
- }
-
- ~ScopedUtfChars() {
- if (mUtfChars) {
- mEnv->ReleaseStringUTFChars(mString, mUtfChars);
- }
- }
-
- const char* c_str() const {
- return mUtfChars;
- }
-
- size_t size() const {
- return strlen(mUtfChars);
- }
-
- // Element access.
- const char& operator[](size_t n) const {
- return mUtfChars[n];
- }
-
-private:
- JNIEnv* mEnv;
- jstring mString;
- const char* mUtfChars;
-
- // Disallow copy and assignment.
- ScopedUtfChars(const ScopedUtfChars&);
- void operator=(const ScopedUtfChars&);
-};
-
-#endif // SCOPED_UTF_CHARS_H_included
diff --git a/include/UniquePtr.h b/include/UniquePtr.h
deleted file mode 100644
index 31db377..0000000
--- a/include/UniquePtr.h
+++ /dev/null
@@ -1,231 +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.
- */
-
-#ifndef UNIQUE_PTR_H_included
-#define UNIQUE_PTR_H_included
-
-#include <cstdlib> // For NULL.
-
-// Default deleter for pointer types.
-template <typename T>
-struct DefaultDelete {
- enum { type_must_be_complete = sizeof(T) };
- DefaultDelete() {}
- void operator()(T* p) const {
- delete p;
- }
-};
-
-// Default deleter for array types.
-template <typename T>
-struct DefaultDelete<T[]> {
- enum { type_must_be_complete = sizeof(T) };
- void operator()(T* p) const {
- delete[] p;
- }
-};
-
-// A smart pointer that deletes the given pointer on destruction.
-// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr
-// and boost::scoped_array).
-// Named to be in keeping with Android style but also to avoid
-// collision with any other implementation, until we can switch over
-// to unique_ptr.
-// Use thus:
-// UniquePtr<C> c(new C);
-template <typename T, typename D = DefaultDelete<T> >
-class UniquePtr {
-public:
- // Construct a new UniquePtr, taking ownership of the given raw pointer.
- explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
- }
-
- ~UniquePtr() {
- reset();
- }
-
- // Accessors.
- T& operator*() const { return *mPtr; }
- T* operator->() const { return mPtr; }
- T* get() const { return mPtr; }
-
- // Returns the raw pointer and hands over ownership to the caller.
- // The pointer will not be deleted by UniquePtr.
- T* release() __attribute__((warn_unused_result)) {
- T* result = mPtr;
- mPtr = NULL;
- return result;
- }
-
- // Takes ownership of the given raw pointer.
- // If this smart pointer previously owned a different raw pointer, that
- // raw pointer will be freed.
- void reset(T* ptr = NULL) {
- if (ptr != mPtr) {
- D()(mPtr);
- mPtr = ptr;
- }
- }
-
-private:
- // The raw pointer.
- T* mPtr;
-
- // Comparing unique pointers is probably a mistake, since they're unique.
- template <typename T2> bool operator==(const UniquePtr<T2>& p) const;
- template <typename T2> bool operator!=(const UniquePtr<T2>& p) const;
-
- // Disallow copy and assignment.
- UniquePtr(const UniquePtr&);
- void operator=(const UniquePtr&);
-};
-
-// Partial specialization for array types. Like std::unique_ptr, this removes
-// operator* and operator-> but adds operator[].
-template <typename T, typename D>
-class UniquePtr<T[], D> {
-public:
- explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) {
- }
-
- ~UniquePtr() {
- reset();
- }
-
- T& operator[](size_t i) const {
- return mPtr[i];
- }
- T* get() const { return mPtr; }
-
- T* release() __attribute__((warn_unused_result)) {
- T* result = mPtr;
- mPtr = NULL;
- return result;
- }
-
- void reset(T* ptr = NULL) {
- if (ptr != mPtr) {
- D()(mPtr);
- mPtr = ptr;
- }
- }
-
-private:
- T* mPtr;
-
- // Disallow copy and assignment.
- UniquePtr(const UniquePtr&);
- void operator=(const UniquePtr&);
-};
-
-#if UNIQUE_PTR_TESTS
-
-// Run these tests with:
-// g++ -g -DUNIQUE_PTR_TESTS -x c++ UniquePtr.h && ./a.out
-
-#include <stdio.h>
-
-static void assert(bool b) {
- if (!b) {
- fprintf(stderr, "FAIL\n");
- abort();
- }
- fprintf(stderr, "OK\n");
-}
-static int cCount = 0;
-struct C {
- C() { ++cCount; }
- ~C() { --cCount; }
-};
-static bool freed = false;
-struct Freer {
- void operator()(int* p) {
- assert(*p == 123);
- free(p);
- freed = true;
- }
-};
-
-int main(int argc, char* argv[]) {
- //
- // UniquePtr<T> tests...
- //
-
- // Can we free a single object?
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- }
- assert(cCount == 0);
- // Does release work?
- C* rawC;
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- rawC = c.release();
- }
- assert(cCount == 1);
- delete rawC;
- // Does reset work?
- {
- UniquePtr<C> c(new C);
- assert(cCount == 1);
- c.reset(new C);
- assert(cCount == 1);
- }
- assert(cCount == 0);
-
- //
- // UniquePtr<T[]> tests...
- //
-
- // Can we free an array?
- {
- UniquePtr<C[]> cs(new C[4]);
- assert(cCount == 4);
- }
- assert(cCount == 0);
- // Does release work?
- {
- UniquePtr<C[]> c(new C[4]);
- assert(cCount == 4);
- rawC = c.release();
- }
- assert(cCount == 4);
- delete[] rawC;
- // Does reset work?
- {
- UniquePtr<C[]> c(new C[4]);
- assert(cCount == 4);
- c.reset(new C[2]);
- assert(cCount == 2);
- }
- assert(cCount == 0);
-
- //
- // Custom deleter tests...
- //
- assert(!freed);
- {
- UniquePtr<int, Freer> i(reinterpret_cast<int*>(malloc(sizeof(int))));
- *i = 123;
- }
- assert(freed);
- return 0;
-}
-#endif
-
-#endif // UNIQUE_PTR_H_included
diff --git a/json/src/main/java/org/json/JSONArray.java b/json/src/main/java/org/json/JSONArray.java
index a885125..f6801aa 100644
--- a/json/src/main/java/org/json/JSONArray.java
+++ b/json/src/main/java/org/json/JSONArray.java
@@ -16,8 +16,10 @@
package org.json;
+import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Iterator;
import java.util.List;
// Note: this class was written without inspecting the non-free org.json sourcecode.
@@ -66,8 +68,11 @@
/* Accept a raw type for API compatibility */
public JSONArray(Collection copyFrom) {
this();
- Collection<?> copyFromTyped = (Collection<?>) copyFrom;
- values.addAll(copyFromTyped);
+ if (copyFrom != null) {
+ for (Iterator it = copyFrom.iterator(); it.hasNext();) {
+ put(JSONObject.wrap(it.next()));
+ }
+ }
}
/**
@@ -104,6 +109,20 @@
}
/**
+ * Creates a new {@code JSONArray} with values from the given primitive array.
+ */
+ public JSONArray(Object array) throws JSONException {
+ if (!array.getClass().isArray()) {
+ throw new JSONException("Not a primitive array: " + array.getClass());
+ }
+ final int length = Array.getLength(array);
+ values = new ArrayList<Object>(length);
+ for (int i = 0; i < length; ++i) {
+ put(JSONObject.wrap(Array.get(array, i)));
+ }
+ }
+
+ /**
* Returns the number of values in this array.
*/
public int length() {
@@ -276,6 +295,17 @@
}
/**
+ * Removes and returns the value at {@code index}, or null if the array has no value
+ * at {@code index}.
+ */
+ public Object remove(int index) {
+ if (index < 0 || index >= values.size()) {
+ return null;
+ }
+ return values.remove(index);
+ }
+
+ /**
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean.
*
diff --git a/json/src/main/java/org/json/JSONObject.java b/json/src/main/java/org/json/JSONObject.java
index c2a656c..ae3b747 100644
--- a/json/src/main/java/org/json/JSONObject.java
+++ b/json/src/main/java/org/json/JSONObject.java
@@ -17,6 +17,7 @@
package org.json;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -133,7 +134,7 @@
if (key == null) {
throw new NullPointerException("key == null");
}
- nameValuePairs.put(key, entry.getValue());
+ nameValuePairs.put(key, wrap(entry.getValue()));
}
}
@@ -721,4 +722,54 @@
throw new AssertionError();
}
}
+
+ /**
+ * Wraps the given object if necessary.
+ *
+ * <p>If the object is null or , returns {@link #NULL}.
+ * If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
+ * If the object is {@code NULL}, no wrapping is necessary.
+ * If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
+ * If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
+ * If the object is a primitive wrapper type or {@code String}, returns the object.
+ * Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
+ * If wrapping fails, returns null.
+ */
+ public static Object wrap(Object o) {
+ if (o == null) {
+ return NULL;
+ }
+ if (o instanceof JSONArray || o instanceof JSONObject) {
+ return o;
+ }
+ if (o.equals(NULL)) {
+ return o;
+ }
+ try {
+ if (o instanceof Collection) {
+ return new JSONArray((Collection) o);
+ } else if (o.getClass().isArray()) {
+ return new JSONArray(o);
+ }
+ if (o instanceof Map) {
+ return new JSONObject((Map) o);
+ }
+ if (o instanceof Boolean ||
+ o instanceof Byte ||
+ o instanceof Character ||
+ o instanceof Double ||
+ o instanceof Float ||
+ o instanceof Integer ||
+ o instanceof Long ||
+ o instanceof Short ||
+ o instanceof String) {
+ return o;
+ }
+ if (o.getClass().getPackage().getName().startsWith("java.")) {
+ return o.toString();
+ }
+ } catch (Exception ignored) {
+ }
+ return null;
+ }
}
diff --git a/json/src/test/java/org/json/JSONArrayTest.java b/json/src/test/java/org/json/JSONArrayTest.java
index 1e72af2..52767db 100644
--- a/json/src/test/java/org/json/JSONArrayTest.java
+++ b/json/src/test/java/org/json/JSONArrayTest.java
@@ -17,6 +17,7 @@
package org.json;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
import junit.framework.TestCase;
@@ -136,7 +137,7 @@
public void testNulls() throws JSONException {
JSONArray array = new JSONArray();
- array.put(3, null);
+ array.put(3, (Collection) null);
array.put(0, JSONObject.NULL);
assertEquals(4, array.length());
assertEquals("[null,null,null,null]", array.toString());
@@ -178,7 +179,7 @@
*/
public void testParseNullYieldsJSONObjectNull() throws JSONException {
JSONArray array = new JSONArray("[\"null\",null]");
- array.put(null);
+ array.put((Collection) null);
assertEquals("null", array.get(0));
assertEquals(JSONObject.NULL, array.get(1));
try {
@@ -296,7 +297,7 @@
public void testJoin() throws JSONException {
JSONArray array = new JSONArray();
- array.put(null);
+ array.put((Collection) null);
assertEquals("null", array.join(" & "));
array.put("\"");
assertEquals("null & \"\\\"\"", array.join(" & "));
@@ -345,7 +346,7 @@
JSONArray values = new JSONArray();
values.put(5.5d);
- values.put(null);
+ values.put((Collection) null);
// null values are stripped!
JSONObject object = values.toJSONObject(keys);
@@ -538,4 +539,16 @@
} catch (JSONException e) {
}
}
+
+ public void test_remove() throws Exception {
+ JSONArray a = new JSONArray();
+ assertEquals(null, a.remove(-1));
+ assertEquals(null, a.remove(0));
+
+ a.put("hello");
+ assertEquals(null, a.remove(-1));
+ assertEquals(null, a.remove(1));
+ assertEquals("hello", a.remove(0));
+ assertEquals(null, a.remove(0));
+ }
}
diff --git a/json/src/test/java/org/json/JSONObjectTest.java b/json/src/test/java/org/json/JSONObjectTest.java
index e192b03..8abd88f 100644
--- a/json/src/test/java/org/json/JSONObjectTest.java
+++ b/json/src/test/java/org/json/JSONObjectTest.java
@@ -18,7 +18,9 @@
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -156,7 +158,7 @@
public void testPutNullRemoves() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", "bar");
- object.put("foo", null);
+ object.put("foo", (Collection) null);
assertEquals(0, object.length());
assertFalse(object.has("foo"));
try {
@@ -734,7 +736,7 @@
}
}
- public void testStringonstructorParseFail() {
+ public void testStringConstructorParseFail() {
try {
new JSONObject("{");
fail();
@@ -813,7 +815,7 @@
public void testNullValue() throws JSONException {
JSONObject object = new JSONObject();
object.put("foo", JSONObject.NULL);
- object.put("bar", null);
+ object.put("bar", (Collection) null);
// there are two ways to represent null; each behaves differently!
assertTrue(object.has("foo"));
@@ -961,4 +963,34 @@
} catch (JSONException e) {
}
}
+
+ public void test_wrap() throws Exception {
+ assertEquals(JSONObject.NULL, JSONObject.wrap(null));
+
+ JSONArray a = new JSONArray();
+ assertEquals(a, JSONObject.wrap(a));
+
+ JSONObject o = new JSONObject();
+ assertEquals(o, JSONObject.wrap(o));
+
+ assertEquals(JSONObject.NULL, JSONObject.wrap(JSONObject.NULL));
+
+ assertTrue(JSONObject.wrap(new byte[0]) instanceof JSONArray);
+ assertTrue(JSONObject.wrap(new ArrayList<String>()) instanceof JSONArray);
+ assertTrue(JSONObject.wrap(new HashMap<String, String>()) instanceof JSONObject);
+ assertTrue(JSONObject.wrap(Double.valueOf(0)) instanceof Double);
+ assertTrue(JSONObject.wrap("hello") instanceof String);
+ assertTrue(JSONObject.wrap(java.nio.channels.Selector.open()) instanceof String);
+ }
+
+ // https://code.google.com/p/android/issues/detail?id=55114
+ public void test_toString_listAsMapValue() throws Exception {
+ ArrayList<Object> list = new ArrayList<Object>();
+ list.add("a");
+ list.add(new ArrayList<String>());
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ map.put("x", "l");
+ map.put("y", list);
+ assertEquals("{\"y\":[\"a\",[]],\"x\":\"l\"}", new JSONObject(map).toString());
+ }
}
diff --git a/json/src/test/java/org/json/ParsingTest.java b/json/src/test/java/org/json/ParsingTest.java
index c38c367..641f5b9 100644
--- a/json/src/test/java/org/json/ParsingTest.java
+++ b/json/src/test/java/org/json/ParsingTest.java
@@ -261,6 +261,8 @@
result.put(key, canonicalize(object.get(key)));
}
return result;
+ } else if (input == null || input.equals(JSONObject.NULL)) {
+ return JSONObject.NULL;
} else {
return input;
}
diff --git a/dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java b/libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
similarity index 100%
rename from dalvik/src/main/java/dalvik/system/BaseDexClassLoader.java
rename to libdvm/src/main/java/dalvik/system/BaseDexClassLoader.java
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/libdvm/src/main/java/dalvik/system/DexFile.java
similarity index 97%
rename from dalvik/src/main/java/dalvik/system/DexFile.java
rename to libdvm/src/main/java/dalvik/system/DexFile.java
index 8db3985..18b730b 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/libdvm/src/main/java/dalvik/system/DexFile.java
@@ -273,12 +273,6 @@
int flags) throws IOException;
/*
- * Open a DEX file based on a {@code byte[]}. The value returned
- * is a magic VM cookie. On failure, a RuntimeException is thrown.
- */
- native private static int openDexFile(byte[] fileContents);
-
- /*
* Close DEX file.
*/
native private static void closeDexFile(int cookie);
diff --git a/dalvik/src/main/java/dalvik/system/DexPathList.java b/libdvm/src/main/java/dalvik/system/DexPathList.java
similarity index 98%
rename from dalvik/src/main/java/dalvik/system/DexPathList.java
rename to libdvm/src/main/java/dalvik/system/DexPathList.java
index 3d9ee3e..a10e90e 100644
--- a/dalvik/src/main/java/dalvik/system/DexPathList.java
+++ b/libdvm/src/main/java/dalvik/system/DexPathList.java
@@ -148,8 +148,7 @@
*
* This order was reversed prior to Gingerbread; see http://b/2933456.
*/
- ArrayList<File> result = splitPaths(
- path, System.getProperty("java.library.path", "."), true);
+ ArrayList<File> result = splitPaths(path, System.getProperty("java.library.path"), true);
return result.toArray(new File[result.size()]);
}
diff --git a/dalvik/src/main/java/dalvik/system/VMDebug.java b/libdvm/src/main/java/dalvik/system/VMDebug.java
similarity index 98%
rename from dalvik/src/main/java/dalvik/system/VMDebug.java
rename to libdvm/src/main/java/dalvik/system/VMDebug.java
index 8f40165..a80cfcc 100644
--- a/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libdvm/src/main/java/dalvik/system/VMDebug.java
@@ -32,7 +32,7 @@
/**
* Specifies the default method trace data file name.
*
- * @deprecated only used in one place, which is unused and deprecated
+ * @deprecated Only used in one place, which is unused and deprecated.
*/
@Deprecated
static public final String DEFAULT_METHOD_TRACE_FILE_NAME = "/sdcard/dmtrace.trace";
@@ -140,7 +140,7 @@
* Start method tracing with default name, size, and with <code>0</code>
* flags.
*
- * @deprecated not used, not needed
+ * @deprecated Not used, not needed.
*/
@Deprecated
public static void startMethodTracing() {
diff --git a/dalvik/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
similarity index 100%
rename from dalvik/src/main/java/dalvik/system/VMRuntime.java
rename to libdvm/src/main/java/dalvik/system/VMRuntime.java
diff --git a/dalvik/src/main/java/dalvik/system/VMStack.java b/libdvm/src/main/java/dalvik/system/VMStack.java
similarity index 82%
rename from dalvik/src/main/java/dalvik/system/VMStack.java
rename to libdvm/src/main/java/dalvik/system/VMStack.java
index 9a2be23..bae1829 100644
--- a/dalvik/src/main/java/dalvik/system/VMStack.java
+++ b/libdvm/src/main/java/dalvik/system/VMStack.java
@@ -59,6 +59,22 @@
native public static Class<?>[] getClasses(int maxDepth);
/**
+ * Returns the first ClassLoader on the call stack that isn't either of
+ * the passed-in ClassLoaders.
+ */
+ public static ClassLoader getClosestUserClassLoader(ClassLoader bootstrap,
+ ClassLoader system) {
+ Class<?>[] stackClasses = VMStack.getClasses(-1);
+ for (Class<?> stackClass : stackClasses) {
+ ClassLoader loader = stackClass.getClassLoader();
+ if (loader != null && loader != bootstrap && loader != system) {
+ return loader;
+ }
+ }
+ return null;
+ }
+
+ /**
* Retrieves the stack trace from the specified thread.
*
* @param t
diff --git a/luni/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
similarity index 95%
rename from luni/src/main/java/java/lang/Class.java
rename to libdvm/src/main/java/java/lang/Class.java
index f618b66..2f26688 100644
--- a/luni/src/main/java/java/lang/Class.java
+++ b/libdvm/src/main/java/java/lang/Class.java
@@ -32,6 +32,7 @@
package java.lang;
+import com.android.dex.Dex;
import dalvik.system.VMStack;
import java.io.InputStream;
import java.io.Serializable;
@@ -56,8 +57,9 @@
import libcore.util.CollectionUtils;
import libcore.util.EmptyArray;
import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.AnnotationAccess;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.Types;
/**
* The in-memory representation of a Java class. This representation serves as
@@ -123,12 +125,39 @@
*/
private transient String name;
+ private transient int dexTypeIndex;
+
private Class() {
// Prevent this class to be instantiated, instance
// should be created by JVM only
}
/**
+ * Returns the dex file from which this class was loaded.
+ * @hide
+ */
+ public native Dex getDex();
+
+ /**
+ * 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
+ *
+ * @hide
+ */
+ public int getTypeIndex() {
+ int result = dexTypeIndex;
+ if (result == 0) { // uncomputed => Dalvik
+ result = AnnotationAccess.computeTypeIndex(getDex(), this);
+ dexTypeIndex = result;
+ }
+ return result;
+ }
+
+ /**
* Get the Signature attribute for this class. Returns null if not found.
*/
private String getSignatureAttribute() {
@@ -388,9 +417,11 @@
* constructor matching the given parameter types.
* {@code (Class[]) null} is equivalent to the empty array.
*
+ * <p>See {@link #getMethod} for details of the search order.
+ * Use {@link #getDeclaredConstructor} if you don't want to search superclasses.
+ *
* @throws NoSuchMethodException
* if the constructor can not be found.
- * @see #getDeclaredConstructor(Class[])
*/
@SuppressWarnings("unchecked")
public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
@@ -502,9 +533,10 @@
* represented by this {@code Class}.
* {@code (Class[]) null} is equivalent to the empty array.
*
+ * <p>Use {@link #getConstructor} if you want to search superclasses.
+ *
* @throws NoSuchMethodException
* if the requested constructor can not be found.
- * @see #getConstructor(Class[])
*/
@SuppressWarnings("unchecked")
public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
@@ -578,11 +610,12 @@
* represented by this {@code Class}.
* {@code (Class[]) null} is equivalent to the empty array.
*
+ * <p>See {@link #getMethod} if you want to search superclasses.
+ *
* @throws NoSuchMethodException
* if the requested method can not be found.
* @throws NullPointerException
* if {@code name} is {@code null}.
- * @see #getMethod(String, Class[])
*/
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
throws NoSuchMethodException {
@@ -774,14 +807,15 @@
* Returns a {@code Method} object which represents the public method with
* the given 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.
+ *
+ * <p>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 its superclasses.
+ *
+ * <p>Use {@link #getDeclaredMethod} if you don't want to search superclasses.
*
* @throws NoSuchMethodException
* if the method can not be found.
- * @see #getDeclaredMethod(String, Class[])
*/
public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
Member member = getConstructorOrMethod(name, true, true, parameterTypes);
@@ -1215,4 +1249,17 @@
System.arraycopy(tail, 0, result, head.length, tail.length);
return result;
}
+
+ /**
+ * 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 getAnnotationDirectoryOffset() {
+ return AnnotationAccess.typeIndexToAnnotationDirectoryOffset(getDex(), getTypeIndex());
+ }
+
}
diff --git a/luni/src/main/java/java/lang/ClassLoader.java b/libdvm/src/main/java/java/lang/ClassLoader.java
similarity index 98%
rename from luni/src/main/java/java/lang/ClassLoader.java
rename to libdvm/src/main/java/java/lang/ClassLoader.java
index c99d57c..c6a80913 100644
--- a/luni/src/main/java/java/lang/ClassLoader.java
+++ b/libdvm/src/main/java/java/lang/ClassLoader.java
@@ -218,13 +218,12 @@
* 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 Use {@link #defineClass(String, byte[], int, int)} instead.
*/
@Deprecated
protected final Class<?> defineClass(byte[] classRep, int offset, int length)
throws ClassFormatError {
-
- return VMClassLoader.defineClass(this, classRep, offset, length);
+ throw new UnsupportedOperationException("can't load this type of class file");
}
/**
@@ -251,9 +250,7 @@
*/
protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
throws ClassFormatError {
-
- // TODO Define a default ProtectionDomain on first use
- return defineClass(className, classRep, offset, length, null);
+ throw new UnsupportedOperationException("can't load this type of class file");
}
/**
@@ -288,8 +285,7 @@
*/
protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
-
- return VMClassLoader.defineClass(this, className, classRep, offset, length);
+ throw new UnsupportedOperationException("can't load this type of class file");
}
/**
diff --git a/luni/src/main/java/java/lang/Daemons.java b/libdvm/src/main/java/java/lang/Daemons.java
similarity index 100%
rename from luni/src/main/java/java/lang/Daemons.java
rename to libdvm/src/main/java/java/lang/Daemons.java
diff --git a/luni/src/main/java/java/lang/Enum.java b/libdvm/src/main/java/java/lang/Enum.java
similarity index 100%
rename from luni/src/main/java/java/lang/Enum.java
rename to libdvm/src/main/java/java/lang/Enum.java
diff --git a/luni/src/main/java/java/lang/Object.java b/libdvm/src/main/java/java/lang/Object.java
similarity index 100%
rename from luni/src/main/java/java/lang/Object.java
rename to libdvm/src/main/java/java/lang/Object.java
diff --git a/luni/src/main/java/java/lang/String.java b/libdvm/src/main/java/java/lang/String.java
similarity index 98%
rename from luni/src/main/java/java/lang/String.java
rename to libdvm/src/main/java/java/lang/String.java
index 89691e7..27469f0 100644
--- a/luni/src/main/java/java/lang/String.java
+++ b/libdvm/src/main/java/java/lang/String.java
@@ -573,7 +573,12 @@
* @throws IndexOutOfBoundsException
* if {@code index < 0} or {@code index >= length()}.
*/
- public native char charAt(int index);
+ 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);
@@ -791,7 +796,7 @@
* @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 Use {@link #getBytes()} or {@link #getBytes(String)} instead.
*/
@Deprecated
public void getBytes(int start, int end, byte[] data, int index) {
@@ -1077,7 +1082,9 @@
*
* @since 1.6
*/
- public native boolean isEmpty();
+ public boolean isEmpty() {
+ return count == 0;
+ }
/**
* Returns the last index of the code point {@code c}, or -1.
@@ -1197,11 +1204,11 @@
}
/**
- * Returns the size of this string.
- *
- * @return the number of characters in this string.
+ * Returns the number of characters in this string.
*/
- public native int length();
+ public int length() {
+ return count;
+ }
/**
* Compares the specified string to this string and compares the specified
@@ -1360,10 +1367,14 @@
// The empty target matches at the start and end and between each character.
int targetLength = targetString.length();
if (targetLength == 0) {
- int resultLength = (count + 2) * replacementString.length();
+ // 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);
- for (int i = offset; i < count; ++i) {
+ int end = offset + count;
+ for (int i = offset; i != end; ++i) {
result.append(value[i]);
result.append(replacementString);
}
@@ -1465,9 +1476,9 @@
}
/**
- * Copies the characters in this string to a character array.
- *
- * @return a character array containing the characters of this string.
+ * 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];
diff --git a/luni/src/main/java/java/lang/Thread.java b/libdvm/src/main/java/java/lang/Thread.java
similarity index 99%
rename from luni/src/main/java/java/lang/Thread.java
rename to libdvm/src/main/java/java/lang/Thread.java
index cc0975f..ee4bdbe 100644
--- a/luni/src/main/java/java/lang/Thread.java
+++ b/libdvm/src/main/java/java/lang/Thread.java
@@ -1034,7 +1034,7 @@
* 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
+ * @deprecated Stopping a thread in this manner is unsafe and can
* leave your application and the VM in an unpredictable state.
*/
@Deprecated
@@ -1044,7 +1044,7 @@
/**
* Throws {@code UnsupportedOperationException}.
- * @deprecated because stopping a thread in this manner is unsafe and can
+ * @deprecated Stopping a thread in this manner is unsafe and can
* leave your application and the VM in an unpredictable state.
*/
@Deprecated
diff --git a/luni/src/main/java/java/lang/ThreadGroup.java b/libdvm/src/main/java/java/lang/ThreadGroup.java
similarity index 98%
rename from luni/src/main/java/java/lang/ThreadGroup.java
rename to libdvm/src/main/java/java/lang/ThreadGroup.java
index e99e99f..7fc6b72 100644
--- a/luni/src/main/java/java/lang/ThreadGroup.java
+++ b/libdvm/src/main/java/java/lang/ThreadGroup.java
@@ -176,7 +176,7 @@
* @param b Used to control low memory implicit suspension
* @return {@code true} (always)
*
- * @deprecated Required deprecated method suspend().
+ * @deprecated Required deprecated method {@link #suspend()}.
*/
@Deprecated
public boolean allowThreadSuspension(boolean b) {
@@ -533,7 +533,7 @@
* @see Thread#resume
* @see #suspend
*
- * @deprecated Requires deprecated method Thread.resume().
+ * @deprecated Requires deprecated method {@link Thread#resume()}.
*/
@SuppressWarnings("deprecation")
@Deprecated
@@ -600,7 +600,7 @@
* @see Thread#stop(Throwable)
* @see ThreadDeath
*
- * @deprecated Requires deprecated method Thread.stop().
+ * @deprecated Requires deprecated method {@link Thread#stop()}.
*/
@SuppressWarnings("deprecation")
@Deprecated
@@ -638,7 +638,7 @@
* @see Thread#suspend
* @see #resume
*
- * @deprecated Requires deprecated method Thread.suspend().
+ * @deprecated Requires deprecated method {@link Thread#suspend()}.
*/
@SuppressWarnings("deprecation")
@Deprecated
diff --git a/luni/src/main/java/java/lang/VMClassLoader.java b/libdvm/src/main/java/java/lang/VMClassLoader.java
similarity index 91%
rename from luni/src/main/java/java/lang/VMClassLoader.java
rename to libdvm/src/main/java/java/lang/VMClassLoader.java
index 8604360..d7162c6 100644
--- a/luni/src/main/java/java/lang/VMClassLoader.java
+++ b/libdvm/src/main/java/java/lang/VMClassLoader.java
@@ -75,12 +75,6 @@
native static Class getPrimitiveClass(char type);
- native static Class defineClass(ClassLoader cl, String name, byte[] data, int offset, int len)
- throws ClassFormatError;
-
- native static Class defineClass(ClassLoader cl, byte[] data, int offset, int len)
- throws ClassFormatError;
-
native static Class findLoadedClass(ClassLoader cl, String name);
/**
diff --git a/luni/src/main/java/java/lang/VMThread.java b/libdvm/src/main/java/java/lang/VMThread.java
similarity index 100%
rename from luni/src/main/java/java/lang/VMThread.java
rename to libdvm/src/main/java/java/lang/VMThread.java
diff --git a/luni/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
similarity index 100%
rename from luni/src/main/java/java/lang/reflect/AccessibleObject.java
rename to libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
diff --git a/luni/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java
similarity index 97%
rename from luni/src/main/java/java/lang/reflect/Constructor.java
rename to libdvm/src/main/java/java/lang/reflect/Constructor.java
index 9a0e03c..531f269 100644
--- a/luni/src/main/java/java/lang/reflect/Constructor.java
+++ b/libdvm/src/main/java/java/lang/reflect/Constructor.java
@@ -35,9 +35,9 @@
import java.lang.annotation.Annotation;
import libcore.util.EmptyArray;
import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.ListOfTypes;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
/**
* This class represents a constructor. Information about the constructor can be
@@ -74,6 +74,8 @@
int slot;
+ private int methodDexIndex;
+
/**
* Prevent this class from being instantiated.
*/
@@ -94,11 +96,17 @@
* @param slot
* the slot of the constructor inside the VM class structure
*/
- private Constructor (Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot){
+ private Constructor(Class<T> declaringClass, Class<?>[] ptypes, Class<?>[] extypes, int slot, int methodDexIndex) {
this.declaringClass = declaringClass;
this.parameterTypes = ptypes;
this.exceptionTypes = extypes; // may be null
this.slot = slot;
+ this.methodDexIndex = methodDexIndex;
+ }
+
+ /** @hide */
+ public int getDexMethodIndex() {
+ return methodDexIndex;
}
@Override /*package*/ String getSignatureAttribute() {
diff --git a/luni/src/main/java/java/lang/reflect/Field.java b/libdvm/src/main/java/java/lang/reflect/Field.java
similarity index 98%
rename from luni/src/main/java/java/lang/reflect/Field.java
rename to libdvm/src/main/java/java/lang/reflect/Field.java
index 0aacb11..fa8e5e7 100644
--- a/luni/src/main/java/java/lang/reflect/Field.java
+++ b/libdvm/src/main/java/java/lang/reflect/Field.java
@@ -35,8 +35,8 @@
import java.lang.annotation.Annotation;
import java.util.Comparator;
import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.Types;
/**
* This class represents a field. Information about the field can be accessed,
@@ -73,6 +73,8 @@
private int slot;
+ private final int fieldDexIndex;
+
private static final char TYPE_BOOLEAN = 'Z';
private static final char TYPE_BYTE = 'B';
@@ -89,25 +91,20 @@
private static final char TYPE_DOUBLE = 'D';
- /**
- * Construct a clone of the given instance.
- *
- * @param orig non-null; the original instance to clone
- */
- /*package*/ Field(Field orig) {
- this(orig.declaringClass, orig.type, orig.name, orig.slot);
-
- // Copy the accessible flag.
- if (orig.flag) {
- this.flag = true;
- }
- }
-
- private Field(Class<?> declaringClass, Class<?> type, String name, int slot) {
+ private Field(Class<?> declaringClass, Class<?> type, String name, int slot, int fieldDexIndex) {
this.declaringClass = declaringClass;
this.type = type;
this.name = name;
this.slot = slot;
+ this.fieldDexIndex = fieldDexIndex;
+ }
+
+ /**
+ * Returns the index of this field's ID in its dex file.
+ * @hide
+ */
+ public int getDexFieldIndex() {
+ return fieldDexIndex;
}
private synchronized void initGenericType() {
diff --git a/luni/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java
similarity index 96%
rename from luni/src/main/java/java/lang/reflect/Method.java
rename to libdvm/src/main/java/java/lang/reflect/Method.java
index b2f970a..028b9ca 100644
--- a/luni/src/main/java/java/lang/reflect/Method.java
+++ b/libdvm/src/main/java/java/lang/reflect/Method.java
@@ -37,9 +37,9 @@
import java.util.Comparator;
import libcore.util.EmptyArray;
import org.apache.harmony.kernel.vm.StringUtils;
-import org.apache.harmony.luni.lang.reflect.GenericSignatureParser;
-import org.apache.harmony.luni.lang.reflect.ListOfTypes;
-import org.apache.harmony.luni.lang.reflect.Types;
+import libcore.reflect.GenericSignatureParser;
+import libcore.reflect.ListOfTypes;
+import libcore.reflect.Types;
/**
* This class represents a method. Information about the method can be accessed,
@@ -80,6 +80,8 @@
private int slot;
+ private final int methodDexIndex;
+
private Class<?> declaringClass;
private String name;
@@ -110,29 +112,19 @@
}
}
- /**
- * Construct a clone of the given instance.
- *
- * @param orig non-null; the original instance to clone
- */
- /*package*/ Method(Method orig) {
- this(orig.declaringClass, orig.parameterTypes, orig.exceptionTypes,
- orig.returnType, orig.name, orig.slot);
-
- // Copy the accessible flag.
- if (orig.flag) {
- this.flag = true;
- }
- }
-
- private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot)
- {
+ private Method(Class<?> declaring, Class<?>[] paramTypes, Class<?>[] exceptTypes, Class<?> returnType, String name, int slot, int methodDexIndex) {
this.declaringClass = declaring;
this.name = name;
this.slot = slot;
this.parameterTypes = paramTypes;
this.exceptionTypes = exceptTypes; // may be null
this.returnType = returnType;
+ this.methodDexIndex = methodDexIndex;
+ }
+
+ /** @hide */
+ public int getDexMethodIndex() {
+ return methodDexIndex;
}
public TypeVariable<Method>[] getTypeParameters() {
diff --git a/luni/src/main/java/java/lang/reflect/Proxy.java b/libdvm/src/main/java/java/lang/reflect/Proxy.java
similarity index 100%
rename from luni/src/main/java/java/lang/reflect/Proxy.java
rename to libdvm/src/main/java/java/lang/reflect/Proxy.java
diff --git a/luni/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java b/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
similarity index 100%
rename from luni/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
rename to libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
diff --git a/luni/src/main/java/sun/misc/Unsafe.java b/libdvm/src/main/java/sun/misc/Unsafe.java
similarity index 100%
rename from luni/src/main/java/sun/misc/Unsafe.java
rename to libdvm/src/main/java/sun/misc/Unsafe.java
diff --git a/luni/src/main/java/java/io/BufferedInputStream.java b/luni/src/main/java/java/io/BufferedInputStream.java
index d45595b..5a810e7 100644
--- a/luni/src/main/java/java/io/BufferedInputStream.java
+++ b/luni/src/main/java/java/io/BufferedInputStream.java
@@ -242,35 +242,14 @@
return -1;
}
- /**
- * Reads at most {@code byteCount} bytes from this stream and stores them in
- * byte array {@code buffer} starting at offset {@code offset}. Returns the
- * number of bytes actually read or -1 if no bytes were read and the end of
- * the stream was encountered. If all the buffered bytes have been used, a
- * mark has not been set and the requested number of bytes is larger than
- * the receiver's buffer size, this implementation bypasses the buffer and
- * simply places the results directly into {@code buffer}.
- *
- * @param buffer
- * the byte array in which to store the bytes read.
- * @return the number of bytes actually read or -1 if end of stream.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code byteCount < 0}, or if
- * {@code offset + byteCount} is greater than the size of
- * {@code buffer}.
- * @throws IOException
- * if the stream is already closed or another IOException
- * occurs.
- */
- @Override
- public synchronized int read(byte[] buffer, int offset, int byteCount) throws IOException {
+ @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
// Use local ref since buf may be invalidated by an unsynchronized
// close()
byte[] localBuf = buf;
if (localBuf == null) {
throw streamClosed();
}
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
if (byteCount == 0) {
return 0;
}
@@ -283,12 +262,12 @@
if (pos < count) {
/* There are bytes available in the buffer. */
int copylength = count - pos >= byteCount ? byteCount : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, copylength);
+ System.arraycopy(localBuf, pos, buffer, byteOffset, copylength);
pos += copylength;
if (copylength == byteCount || localIn.available() == 0) {
return copylength;
}
- offset += copylength;
+ byteOffset += copylength;
required = byteCount - copylength;
} else {
required = byteCount;
@@ -301,7 +280,7 @@
* buffer, simply read the bytes directly bypassing the buffer.
*/
if (markpos == -1 && required >= localBuf.length) {
- read = localIn.read(buffer, offset, required);
+ read = localIn.read(buffer, byteOffset, required);
if (read == -1) {
return required == byteCount ? -1 : byteCount - required;
}
@@ -318,7 +297,7 @@
}
read = count - pos >= required ? required : count - pos;
- System.arraycopy(localBuf, pos, buffer, offset, read);
+ System.arraycopy(localBuf, pos, buffer, byteOffset, read);
pos += read;
}
required -= read;
@@ -328,7 +307,7 @@
if (localIn.available() == 0) {
return byteCount - required;
}
- offset += read;
+ byteOffset += read;
}
}
diff --git a/luni/src/main/java/java/io/BufferedReader.java b/luni/src/main/java/java/io/BufferedReader.java
index 9fba039..c72e798 100644
--- a/luni/src/main/java/java/io/BufferedReader.java
+++ b/luni/src/main/java/java/io/BufferedReader.java
@@ -71,6 +71,21 @@
private int markLimit = -1;
/**
+ * readLine returns a line as soon as it sees '\n' or '\r'. In the latter
+ * case, there might be a following '\n' that should be treated as part of
+ * the same line ending. Both readLine and all read methods are supposed
+ * to skip the '\n' (and clear this field) but only readLine looks for '\r'
+ * and sets it.
+ */
+ private boolean lastWasCR;
+
+ /**
+ * We also need to keep the 'lastWasCR' state for the mark position, in case
+ * we reset to there.
+ */
+ private boolean markedLastWasCR;
+
+ /**
* Constructs a new {@code BufferedReader}, providing {@code in} with a buffer
* of 8192 characters.
*
@@ -195,7 +210,8 @@
synchronized (lock) {
checkNotClosed();
this.markLimit = markLimit;
- mark = pos;
+ this.mark = pos;
+ this.markedLastWasCR = lastWasCR;
}
}
@@ -234,16 +250,24 @@
public int read() throws IOException {
synchronized (lock) {
checkNotClosed();
- /* Are there buffered characters available? */
- if (pos < end || fillBuf() != -1) {
- return buf[pos++];
+ int ch = readChar();
+ if (lastWasCR && ch == '\n') {
+ ch = readChar();
}
- return -1;
+ lastWasCR = false;
+ return ch;
}
}
+ private int readChar() throws IOException {
+ if (pos < end || fillBuf() != -1) {
+ return buf[pos++];
+ }
+ return -1;
+ }
+
/**
- * Reads at most {@code length} characters from this reader and stores them
+ * Reads up to {@code length} characters from this reader and stores them
* at {@code offset} in the character array {@code buffer}. Returns the
* number of characters actually read or -1 if the end of the source reader
* has been reached. If all the buffered characters have been used, a mark
@@ -251,20 +275,8 @@
* this readers buffer size, BufferedReader bypasses the buffer and simply
* places the results directly into {@code buffer}.
*
- * @param buffer
- * the character array to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the chars read
- * from this reader.
- * @param length
- * the maximum number of characters to read, must be
- * non-negative.
- * @return number of characters read or -1 if the end of the source reader
- * has been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the size of
- * {@code buffer}.
+ * if {@code offset < 0 || length < 0 || offset + length > buffer.length}.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/
@@ -273,12 +285,15 @@
synchronized (lock) {
checkNotClosed();
Arrays.checkOffsetAndCount(buffer.length, offset, length);
+ if (length == 0) {
+ return 0;
+ }
+
+ maybeSwallowLF();
+
int outstanding = length;
while (outstanding > 0) {
-
- /*
- * If there are chars in the buffer, grab those first.
- */
+ // If there are chars in the buffer, grab those first.
int available = end - pos;
if (available > 0) {
int count = available >= outstanding ? outstanding : available;
@@ -321,7 +336,10 @@
}
int count = length - outstanding;
- return (count > 0 || count == length) ? count : -1;
+ if (count > 0) {
+ return count;
+ }
+ return -1;
}
}
@@ -330,9 +348,16 @@
* this character is a newline character ("\n"), it is discarded.
*/
final void chompNewline() throws IOException {
- if ((pos != end || fillBuf() != -1)
- && buf[pos] == '\n') {
- pos++;
+ if ((pos != end || fillBuf() != -1) && buf[pos] == '\n') {
+ ++pos;
+ }
+ }
+
+ // If the last character was CR and the next character is LF, skip it.
+ private void maybeSwallowLF() throws IOException {
+ if (lastWasCR) {
+ chompNewline();
+ lastWasCR = false;
}
}
@@ -350,77 +375,45 @@
public String readLine() throws IOException {
synchronized (lock) {
checkNotClosed();
- /* has the underlying stream been exhausted? */
- if (pos == end && fillBuf() == -1) {
- return null;
- }
- for (int charPos = pos; charPos < end; charPos++) {
- char ch = buf[charPos];
- if (ch > '\r') {
- continue;
- }
- if (ch == '\n') {
- String res = new String(buf, pos, charPos - pos);
- pos = charPos + 1;
- return res;
- } else if (ch == '\r') {
- String res = new String(buf, pos, charPos - pos);
- pos = charPos + 1;
- if (((pos < end) || (fillBuf() != -1))
- && (buf[pos] == '\n')) {
- pos++;
- }
- return res;
+
+ maybeSwallowLF();
+
+ // Do we have a whole line in the buffer?
+ for (int i = pos; i < end; ++i) {
+ char ch = buf[i];
+ if (ch == '\n' || ch == '\r') {
+ String line = new String(buf, pos, i - pos);
+ pos = i + 1;
+ lastWasCR = (ch == '\r');
+ return line;
}
}
- char eol = '\0';
- StringBuilder result = new StringBuilder(80);
- /* Typical Line Length */
-
+ // Accumulate buffers in a StringBuilder until we've read a whole line.
+ StringBuilder result = new StringBuilder(end - pos + 80);
result.append(buf, pos, end - pos);
while (true) {
pos = end;
-
- /* Are there buffered characters available? */
- if (eol == '\n') {
- return result.toString();
- }
- // attempt to fill buffer
if (fillBuf() == -1) {
- // characters or null.
- return result.length() > 0 || eol != '\0'
- ? result.toString()
- : null;
+ // If there's no more input, return what we've read so far, if anything.
+ return (result.length() > 0) ? result.toString() : null;
}
- for (int charPos = pos; charPos < end; charPos++) {
- char c = buf[charPos];
- if (eol == '\0') {
- if ((c == '\n' || c == '\r')) {
- eol = c;
- }
- } else if (eol == '\r' && c == '\n') {
- if (charPos > pos) {
- result.append(buf, pos, charPos - pos - 1);
- }
- pos = charPos + 1;
- return result.toString();
- } else {
- if (charPos > pos) {
- result.append(buf, pos, charPos - pos - 1);
- }
- pos = charPos;
+
+ // Do we have a whole line in the buffer now?
+ for (int i = pos; i < end; ++i) {
+ char ch = buf[i];
+ if (ch == '\n' || ch == '\r') {
+ result.append(buf, pos, i - pos);
+ pos = i + 1;
+ lastWasCR = (ch == '\r');
return result.toString();
}
}
- if (eol == '\0') {
- result.append(buf, pos, end - pos);
- } else {
- result.append(buf, pos, end - pos - 1);
- }
+
+ // Add this whole buffer to the line-in-progress and try again...
+ result.append(buf, pos, end - pos);
}
}
-
}
/**
@@ -459,26 +452,23 @@
if (mark == -1) {
throw new IOException("Invalid mark");
}
- pos = mark;
+ this.pos = mark;
+ this.lastWasCR = this.markedLastWasCR;
}
}
/**
- * Skips {@code charCount} chars in this stream. Subsequent calls to
+ * Skips at most {@code charCount} chars in this stream. Subsequent calls to
* {@code read} will not return these chars unless {@code reset} is
* used.
*
* <p>Skipping characters may invalidate a mark if {@code markLimit}
* is surpassed.
*
- * @param charCount the maximum number of characters to skip.
* @return the number of characters actually skipped.
* @throws IllegalArgumentException if {@code charCount < 0}.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
- * @see #mark(int)
- * @see #markSupported()
- * @see #reset()
*/
@Override
public long skip(long charCount) throws IOException {
@@ -487,9 +477,6 @@
}
synchronized (lock) {
checkNotClosed();
- if (charCount < 1) {
- return 0;
- }
if (end - pos >= charCount) {
pos += charCount;
return charCount;
diff --git a/luni/src/main/java/java/io/ByteArrayInputStream.java b/luni/src/main/java/java/io/ByteArrayInputStream.java
index 0a8c453..7a6cc50 100644
--- a/luni/src/main/java/java/io/ByteArrayInputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayInputStream.java
@@ -141,41 +141,19 @@
return pos < count ? buf[pos++] & 0xFF : -1;
}
- /**
- * Reads at most {@code len} bytes from this stream and stores
- * them in byte array {@code b} starting at {@code offset}. This
- * implementation reads bytes from the source byte array.
- *
- * @param buffer
- * the byte array in which to store the bytes read.
- * @param offset
- * the initial position in {@code b} to store the bytes read from
- * this stream.
- * @param length
- * the maximum number of bytes to store in {@code b}.
- * @return the number of bytes actually read or -1 if no bytes were read and
- * the end of the stream was encountered.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the size of
- * {@code b}.
- * @throws NullPointerException
- * if {@code b} is {@code null}.
- */
- @Override
- public synchronized int read(byte[] buffer, int offset, int length) {
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
+ @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
// Are there any bytes available?
if (this.pos >= this.count) {
return -1;
}
- if (length == 0) {
+ if (byteCount == 0) {
return 0;
}
- int copylen = this.count - pos < length ? this.count - pos : length;
- System.arraycopy(this.buf, pos, buffer, offset, copylen);
+ int copylen = this.count - pos < byteCount ? this.count - pos : byteCount;
+ System.arraycopy(this.buf, pos, buffer, byteOffset, copylen);
pos += copylen;
return copylen;
}
diff --git a/luni/src/main/java/java/io/ByteArrayOutputStream.java b/luni/src/main/java/java/io/ByteArrayOutputStream.java
index ff9c7df..45f217b 100644
--- a/luni/src/main/java/java/io/ByteArrayOutputStream.java
+++ b/luni/src/main/java/java/io/ByteArrayOutputStream.java
@@ -149,7 +149,7 @@
* the high byte of each resulting Unicode character.
* @return this stream's current contents as a string with the high byte set
* to {@code hibyte}.
- * @deprecated Use {@link #toString()}.
+ * @deprecated Use {@link #toString()} instead.
*/
@Deprecated
public String toString(int hibyte) {
diff --git a/luni/src/main/java/java/io/CharArrayReader.java b/luni/src/main/java/java/io/CharArrayReader.java
index 366efcf..c5baa32 100644
--- a/luni/src/main/java/java/io/CharArrayReader.java
+++ b/luni/src/main/java/java/io/CharArrayReader.java
@@ -184,34 +184,23 @@
}
/**
- * Reads at most {@code count} characters from this CharArrayReader and
- * stores them at {@code offset} in the character array {@code buf}.
+ * Reads up to {@code count} characters from this CharArrayReader and
+ * stores them at {@code offset} in the character array {@code buffer}.
* Returns the number of characters actually read or -1 if the end of reader
* was encountered.
*
- * @param buffer
- * the character array to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param len
- * the maximum number of characters to read.
- * @return number of characters read or -1 if the end of the reader has been
- * reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code len < 0}, or if
- * {@code offset + len} is bigger than the size of
- * {@code buffer}.
+ * if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
* @throws IOException
* if this reader is closed.
*/
@Override
- public int read(char[] buffer, int offset, int len) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, len);
+ public int read(char[] buffer, int offset, int count) throws IOException {
+ Arrays.checkOffsetAndCount(buffer.length, offset, count);
synchronized (lock) {
checkNotClosed();
if (pos < this.count) {
- int bytesRead = pos + len > this.count ? this.count - pos : len;
+ int bytesRead = pos + count > this.count ? this.count - pos : count;
System.arraycopy(this.buf, pos, buffer, offset, bytesRead);
pos += bytesRead;
return bytesRead;
diff --git a/luni/src/main/java/java/io/DataInputStream.java b/luni/src/main/java/java/io/DataInputStream.java
index 7826852..3b1a6d0 100644
--- a/luni/src/main/java/java/io/DataInputStream.java
+++ b/luni/src/main/java/java/io/DataInputStream.java
@@ -59,29 +59,8 @@
return super.read(buffer);
}
- /**
- * Reads at most {@code length} bytes from this stream and stores them in
- * the byte array {@code buffer} starting at {@code offset}. Returns the
- * number of bytes that have been read or -1 if no bytes have been read and
- * the end of the stream has been reached.
- *
- * @param buffer
- * the byte array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes
- * read from this stream.
- * @param length
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes that have been read or -1 if the end of the
- * stream has been reached.
- * @throws IOException
- * if a problem occurs while reading from this stream.
- * @see DataOutput#write(byte[])
- * @see DataOutput#write(byte[], int, int)
- */
- @Override
- public final int read(byte[] buffer, int offset, int length) throws IOException {
- return in.read(buffer, offset, length);
+ @Override public final int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ return in.read(buffer, byteOffset, byteCount);
}
public final boolean readBoolean() throws IOException {
@@ -125,6 +104,10 @@
return Memory.peekInt(scratch, 0, ByteOrder.BIG_ENDIAN);
}
+ /**
+ * @deprecated This method cannot be trusted to convert bytes to characters correctly.
+ * Wrap this stream with a {@link BufferedReader} instead.
+ */
@Deprecated
public final String readLine() throws IOException {
StringBuilder line = new StringBuilder(80); // Typical line length
diff --git a/luni/src/main/java/java/io/File.java b/luni/src/main/java/java/io/File.java
index ec87fed..a8b4810 100644
--- a/luni/src/main/java/java/io/File.java
+++ b/luni/src/main/java/java/io/File.java
@@ -27,7 +27,7 @@
import libcore.io.IoUtils;
import libcore.io.Libcore;
import libcore.io.StructStat;
-import libcore.io.StructStatFs;
+import libcore.io.StructStatVfs;
import org.apache.harmony.luni.util.DeleteOnExit;
import static libcore.io.OsConstants.*;
@@ -487,8 +487,6 @@
/**
* Returns the path of this file.
- *
- * @return this file's path.
*/
public String getPath() {
return path;
@@ -1084,8 +1082,8 @@
* @return a URL for this file.
* @throws java.net.MalformedURLException
* if the path cannot be transformed into a URL.
- * @deprecated use {@link #toURI} and {@link java.net.URI#toURL} to get
- * correct escaping of illegal characters.
+ * @deprecated Use {@link #toURI} and {@link java.net.URI#toURL} to
+ * correctly escape illegal characters.
*/
@Deprecated
public URL toURL() throws java.net.MalformedURLException {
@@ -1132,7 +1130,7 @@
*/
public long getTotalSpace() {
try {
- StructStatFs sb = Libcore.os.statfs(path);
+ StructStatVfs sb = Libcore.os.statvfs(path);
return sb.f_blocks * sb.f_bsize; // total block count * block size in bytes.
} catch (ErrnoException errnoException) {
return 0;
@@ -1154,7 +1152,7 @@
*/
public long getUsableSpace() {
try {
- StructStatFs sb = Libcore.os.statfs(path);
+ StructStatVfs sb = Libcore.os.statvfs(path);
return sb.f_bavail * sb.f_bsize; // non-root free block count * block size in bytes.
} catch (ErrnoException errnoException) {
return 0;
@@ -1172,7 +1170,7 @@
*/
public long getFreeSpace() {
try {
- StructStatFs sb = Libcore.os.statfs(path);
+ StructStatVfs sb = Libcore.os.statvfs(path);
return sb.f_bfree * sb.f_bsize; // free block count * block size in bytes.
} catch (ErrnoException errnoException) {
return 0;
diff --git a/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java
index 537607a..b2e620f 100644
--- a/luni/src/main/java/java/io/FileInputStream.java
+++ b/luni/src/main/java/java/io/FileInputStream.java
@@ -53,7 +53,7 @@
* @see BufferedInputStream
* @see FileOutputStream
*/
-public class FileInputStream extends InputStream implements Closeable {
+public class FileInputStream extends InputStream {
private FileDescriptor fd;
private final boolean shouldClose;
diff --git a/luni/src/main/java/java/io/FileOutputStream.java b/luni/src/main/java/java/io/FileOutputStream.java
index 6787112..e04ab5f 100644
--- a/luni/src/main/java/java/io/FileOutputStream.java
+++ b/luni/src/main/java/java/io/FileOutputStream.java
@@ -50,7 +50,7 @@
* @see BufferedOutputStream
* @see FileInputStream
*/
-public class FileOutputStream extends OutputStream implements Closeable {
+public class FileOutputStream extends OutputStream {
private FileDescriptor fd;
private final boolean shouldClose;
diff --git a/luni/src/main/java/java/io/FilterInputStream.java b/luni/src/main/java/java/io/FilterInputStream.java
index 2bf13e2..4092cd4 100644
--- a/luni/src/main/java/java/io/FilterInputStream.java
+++ b/luni/src/main/java/java/io/FilterInputStream.java
@@ -114,28 +114,8 @@
return in.read();
}
- /**
- * Reads at most {@code count} bytes from this stream and stores them in the
- * byte array {@code buffer} starting at {@code offset}. Returns the number
- * of bytes actually read or -1 if no bytes have been read and the end of
- * this stream has been reached. This implementation reads bytes from the
- * filtered stream.
- *
- * @param buffer
- * the byte array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes
- * read from this stream.
- * @param count
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes actually read or -1 if the end of the
- * filtered stream has been reached while reading.
- * @throws IOException
- * if this stream is closed or another I/O error occurs.
- */
- @Override
- public int read(byte[] buffer, int offset, int count) throws IOException {
- return in.read(buffer, offset, count);
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ return in.read(buffer, byteOffset, byteCount);
}
/**
diff --git a/luni/src/main/java/java/io/FilterReader.java b/luni/src/main/java/java/io/FilterReader.java
index 43beb8c..e93fe9c 100644
--- a/luni/src/main/java/java/io/FilterReader.java
+++ b/luni/src/main/java/java/io/FilterReader.java
@@ -116,20 +116,11 @@
}
/**
- * Reads at most {@code count} characters from the filtered reader and stores them
+ * Reads up to {@code count} characters from the filtered reader and stores them
* in the byte array {@code buffer} starting at {@code offset}. Returns the
* number of characters actually read or -1 if no characters were read and
* the end of the filtered reader was encountered.
*
- * @param buffer
- * the char array in which to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param count
- * the maximum number of characters to store in {@code buffer}.
- * @return the number of characters actually read or -1 if the end of the
- * filtered reader has been reached while reading.
* @throws IOException
* if an error occurs while reading from this reader.
*/
diff --git a/luni/src/main/java/java/io/HistoricalCharsetNames.java b/luni/src/main/java/java/io/HistoricalCharsetNames.java
deleted file mode 100644
index b0d5498..0000000
--- a/luni/src/main/java/java/io/HistoricalCharsetNames.java
+++ /dev/null
@@ -1,175 +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 java.io;
-
-import java.nio.charset.Charset;
-import java.util.HashMap;
-
-/**
- * This could have been in Charset or Charsets, but all code uses those classes whereas no code
- * should need to use this, so let's not make good code pay to initialize this map.
- */
-class HistoricalCharsetNames {
- private static final HashMap<String, String> historicalNames = new HashMap<String, String>();
- static {
- historicalNames.put("Big5-HKSCS", "Big5_HKSCS");
- historicalNames.put("EUC-JP", "EUC_JP");
- historicalNames.put("EUC-KR", "EUC_KR");
- historicalNames.put("GB2312", "EUC_CN");
- historicalNames.put("IBM-Thai", "Cp838");
- historicalNames.put("IBM00858", "Cp858");
- historicalNames.put("IBM01140", "Cp1140");
- historicalNames.put("IBM01141", "Cp1141");
- historicalNames.put("IBM01142", "Cp1142");
- historicalNames.put("IBM01143", "Cp1143");
- historicalNames.put("IBM01144", "Cp1144");
- historicalNames.put("IBM01145", "Cp1145");
- historicalNames.put("IBM01146", "Cp1146");
- historicalNames.put("IBM01147", "Cp1147");
- historicalNames.put("IBM01148", "Cp1148");
- historicalNames.put("IBM01149", "Cp1149");
- historicalNames.put("IBM037", "Cp037");
- historicalNames.put("IBM1026", "Cp1026");
- historicalNames.put("IBM1047", "Cp1047");
- historicalNames.put("IBM273", "Cp273");
- historicalNames.put("IBM277", "Cp277");
- historicalNames.put("IBM278", "Cp278");
- historicalNames.put("IBM280", "Cp280");
- historicalNames.put("IBM284", "Cp284");
- historicalNames.put("IBM285", "Cp285");
- historicalNames.put("IBM297", "Cp297");
- historicalNames.put("IBM420", "Cp420");
- historicalNames.put("IBM424", "Cp424");
- historicalNames.put("IBM437", "Cp437");
- historicalNames.put("IBM500", "Cp500");
- historicalNames.put("IBM775", "Cp775");
- historicalNames.put("IBM850", "Cp850");
- historicalNames.put("IBM852", "Cp852");
- historicalNames.put("IBM855", "Cp855");
- historicalNames.put("IBM857", "Cp857");
- historicalNames.put("IBM860", "Cp860");
- historicalNames.put("IBM861", "Cp861");
- historicalNames.put("IBM862", "Cp862");
- historicalNames.put("IBM863", "Cp863");
- historicalNames.put("IBM864", "Cp864");
- historicalNames.put("IBM865", "Cp865");
- historicalNames.put("IBM866", "Cp866");
- historicalNames.put("IBM868", "Cp868");
- historicalNames.put("IBM869", "Cp869");
- historicalNames.put("IBM870", "Cp870");
- historicalNames.put("IBM871", "Cp871");
- historicalNames.put("IBM918", "Cp918");
- historicalNames.put("ISO-2022-CN", "ISO2022CN");
- historicalNames.put("ISO-2022-JP", "ISO2022JP");
- historicalNames.put("ISO-2022-KR", "ISO2022KR");
- historicalNames.put("ISO-8859-1", "ISO8859_1");
- historicalNames.put("ISO-8859-13", "ISO8859_13");
- historicalNames.put("ISO-8859-15", "ISO8859_15");
- historicalNames.put("ISO-8859-2", "ISO8859_2");
- historicalNames.put("ISO-8859-3", "ISO8859_3");
- historicalNames.put("ISO-8859-4", "ISO8859_4");
- historicalNames.put("ISO-8859-5", "ISO8859_5");
- historicalNames.put("ISO-8859-6", "ISO8859_6");
- historicalNames.put("ISO-8859-7", "ISO8859_7");
- historicalNames.put("ISO-8859-8", "ISO8859_8");
- historicalNames.put("ISO-8859-9", "ISO8859_9");
- historicalNames.put("KOI8-R", "KOI8_R");
- historicalNames.put("Shift_JIS", "SJIS");
- historicalNames.put("TIS-620", "TIS620");
- historicalNames.put("US-ASCII", "ASCII");
- historicalNames.put("UTF-16BE", "UnicodeBigUnmarked");
- historicalNames.put("UTF-16LE", "UnicodeLittleUnmarked");
- historicalNames.put("UTF-8", "UTF8");
- historicalNames.put("windows-1250", "Cp1250");
- historicalNames.put("windows-1251", "Cp1251");
- historicalNames.put("windows-1252", "Cp1252");
- historicalNames.put("windows-1253", "Cp1253");
- historicalNames.put("windows-1254", "Cp1254");
- historicalNames.put("windows-1255", "Cp1255");
- historicalNames.put("windows-1256", "Cp1256");
- historicalNames.put("windows-1257", "Cp1257");
- historicalNames.put("windows-1258", "Cp1258");
- historicalNames.put("windows-31j", "MS932");
- historicalNames.put("x-Big5-Solaris", "Big5_Solaris");
- historicalNames.put("x-euc-jp-linux", "EUC_JP_LINUX");
- historicalNames.put("x-EUC-TW", "EUC_TW");
- historicalNames.put("x-eucJP-Open", "EUC_JP_Solaris");
- historicalNames.put("x-IBM1006", "Cp1006");
- historicalNames.put("x-IBM1025", "Cp1025");
- historicalNames.put("x-IBM1046", "Cp1046");
- historicalNames.put("x-IBM1097", "Cp1097");
- historicalNames.put("x-IBM1098", "Cp1098");
- historicalNames.put("x-IBM1112", "Cp1112");
- historicalNames.put("x-IBM1122", "Cp1122");
- historicalNames.put("x-IBM1123", "Cp1123");
- historicalNames.put("x-IBM1124", "Cp1124");
- historicalNames.put("x-IBM1381", "Cp1381");
- historicalNames.put("x-IBM1383", "Cp1383");
- historicalNames.put("x-IBM33722", "Cp33722");
- historicalNames.put("x-IBM737", "Cp737");
- historicalNames.put("x-IBM856", "Cp856");
- historicalNames.put("x-IBM874", "Cp874");
- historicalNames.put("x-IBM875", "Cp875");
- historicalNames.put("x-IBM921", "Cp921");
- historicalNames.put("x-IBM922", "Cp922");
- historicalNames.put("x-IBM930", "Cp930");
- historicalNames.put("x-IBM933", "Cp933");
- historicalNames.put("x-IBM935", "Cp935");
- historicalNames.put("x-IBM937", "Cp937");
- historicalNames.put("x-IBM939", "Cp939");
- historicalNames.put("x-IBM942", "Cp942");
- historicalNames.put("x-IBM942C", "Cp942C");
- historicalNames.put("x-IBM943", "Cp943");
- historicalNames.put("x-IBM943C", "Cp943C");
- historicalNames.put("x-IBM948", "Cp948");
- historicalNames.put("x-IBM949", "Cp949");
- historicalNames.put("x-IBM949C", "Cp949C");
- historicalNames.put("x-IBM950", "Cp950");
- historicalNames.put("x-IBM964", "Cp964");
- historicalNames.put("x-IBM970", "Cp970");
- historicalNames.put("x-ISCII91", "ISCII91");
- historicalNames.put("x-ISO-2022-CN-CNS", "ISO2022CN");
- historicalNames.put("x-ISO-2022-CN-GB", "ISO2022CN");
- historicalNames.put("x-JISAutoDetect", "JISAutoDetect");
- historicalNames.put("x-MacArabic", "MacArabic");
- historicalNames.put("x-MacCentralEurope", "MacCentralEurope");
- historicalNames.put("x-MacCroatian", "MacCroatian");
- historicalNames.put("x-MacCyrillic", "MacCyrillic");
- historicalNames.put("x-MacDingbat", "MacDingbat");
- historicalNames.put("x-MacGreek", "MacGreek");
- historicalNames.put("x-MacHebrew", "MacHebrew");
- historicalNames.put("x-MacIceland", "MacIceland");
- historicalNames.put("x-MacRoman", "MacRoman");
- historicalNames.put("x-MacRomania", "MacRomania");
- historicalNames.put("x-MacSymbol", "MacSymbol");
- historicalNames.put("x-MacThai", "MacThai");
- historicalNames.put("x-MacTurkish", "MacTurkish");
- historicalNames.put("x-MacUkraine", "MacUkraine");
- historicalNames.put("x-MS950-HKSCS", "MS950_HKSCS");
- historicalNames.put("x-mswin-936", "MS936");
- historicalNames.put("x-PCK", "PCK");
- historicalNames.put("x-windows-874", "MS874");
- historicalNames.put("x-windows-949", "MS949");
- historicalNames.put("x-windows-950", "MS950");
- }
-
- public static String get(Charset charset) {
- String modernName = charset.name();
- String result = historicalNames.get(modernName);
- return (result != null) ? result : modernName;
- }
-}
diff --git a/luni/src/main/java/java/io/InputStream.java b/luni/src/main/java/java/io/InputStream.java
index 561e057..973382e 100644
--- a/luni/src/main/java/java/io/InputStream.java
+++ b/luni/src/main/java/java/io/InputStream.java
@@ -150,7 +150,6 @@
* reached. Blocks until one byte has been read, the end of the source
* stream is detected or an exception is thrown.
*
- * @return the byte read or -1 if the end of stream has been reached.
* @throws IOException
* if the stream is closed or another IOException occurs.
*/
@@ -164,28 +163,19 @@
}
/**
- * Reads at most {@code length} bytes from this stream and stores them in
- * the byte array {@code b} starting at {@code offset}.
+ * Reads up to {@code byteCount} bytes from this stream and stores them in
+ * the byte array {@code buffer} starting at {@code byteOffset}.
+ * Returns the number of bytes actually read or -1 if the end of the stream
+ * has been reached.
*
- * @param buffer
- * the byte array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes read
- * from this stream.
- * @param length
- * the maximum number of bytes to store in {@code b}.
- * @return the number of bytes actually read or -1 if the end of the stream
- * has been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code b}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
* @throws IOException
* if the stream is closed or another IOException occurs.
*/
- public int read(byte[] buffer, int offset, int length) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- for (int i = 0; i < length; i++) {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+ for (int i = 0; i < byteCount; ++i) {
int c;
try {
if ((c = read()) == -1) {
@@ -197,9 +187,9 @@
}
throw e;
}
- buffer[offset + i] = (byte) c;
+ buffer[byteOffset + i] = (byte) c;
}
- return length;
+ return byteCount;
}
/**
diff --git a/luni/src/main/java/java/io/InputStreamReader.java b/luni/src/main/java/java/io/InputStreamReader.java
index d3650dc..01e7f29 100644
--- a/luni/src/main/java/java/io/InputStreamReader.java
+++ b/luni/src/main/java/java/io/InputStreamReader.java
@@ -149,7 +149,7 @@
}
/**
- * Returns the historical name of the encoding used by this writer to convert characters to
+ * Returns the canonical name of the encoding used by this writer to convert characters to
* bytes, or null if this writer has been closed. Most callers should probably keep
* track of the String or Charset they passed in; this method may not return the same
* name.
@@ -158,7 +158,7 @@
if (!isOpen()) {
return null;
}
- return HistoricalCharsetNames.get(decoder.charset());
+ return decoder.charset().name();
}
/**
@@ -185,42 +185,31 @@
}
/**
- * Reads at most {@code length} characters from this reader and stores them
- * at position {@code offset} in the character array {@code buf}. Returns
+ * Reads up to {@code count} characters from this reader and stores them
+ * at position {@code offset} in the character array {@code buffer}. Returns
* the number of characters actually read or -1 if the end of the reader has
* been reached. The bytes are either obtained from converting bytes in this
* reader's buffer or by first filling the buffer from the source
* InputStream and then reading from the buffer.
*
- * @param buffer
- * the array to store the characters read.
- * @param offset
- * the initial position in {@code buf} to store the characters
- * read from this reader.
- * @param length
- * the maximum number of characters to read.
- * @return the number of characters read or -1 if the end of the reader has
- * been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code buf}.
+ * if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/
@Override
- public int read(char[] buffer, int offset, int length) throws IOException {
+ public int read(char[] buffer, int offset, int count) throws IOException {
synchronized (lock) {
if (!isOpen()) {
throw new IOException("InputStreamReader is closed");
}
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- if (length == 0) {
+ Arrays.checkOffsetAndCount(buffer.length, offset, count);
+ if (count == 0) {
return 0;
}
- CharBuffer out = CharBuffer.wrap(buffer, offset, length);
+ CharBuffer out = CharBuffer.wrap(buffer, offset, count);
CoderResult result = CoderResult.UNDERFLOW;
// bytes.remaining() indicates number of bytes in buffer
diff --git a/luni/src/main/java/java/io/LineNumberInputStream.java b/luni/src/main/java/java/io/LineNumberInputStream.java
index 4d1cf14..de6584e 100644
--- a/luni/src/main/java/java/io/LineNumberInputStream.java
+++ b/luni/src/main/java/java/io/LineNumberInputStream.java
@@ -27,7 +27,7 @@
* When using {@code read}, line terminator sequences are always translated into
* {@code '\n'}.
*
- * @deprecated Use {@link LineNumberReader}
+ * @deprecated Use {@link LineNumberReader} instead.
*/
@Deprecated
public class LineNumberInputStream extends FilterInputStream {
@@ -138,38 +138,27 @@
}
/**
- * Reads at most {@code length} bytes from the filtered stream and stores
- * them in the byte array {@code buffer} starting at {@code offset}.
+ * Reads up to {@code byteCount} bytes from the filtered stream and stores
+ * them in the byte array {@code buffer} starting at {@code byteOffset}.
* Returns the number of bytes actually read or -1 if no bytes have been
* read and the end of this stream has been reached.
- * <p>
- * The line number count is incremented if a line terminator is encountered.
+ *
+ * <p>The line number count is incremented if a line terminator is encountered.
* Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
* {@code "\r\n"}. Line terminator sequences are always translated into
* {@code '\n'}.
*
- * @param buffer
- * the array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes read
- * from this stream.
- * @param length
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes actually read or -1 if the end of the
- * filtered stream has been reached while reading.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code buffer}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
* @throws IOException
* if this stream is closed or another IOException occurs.
* @throws NullPointerException
- * if {@code buffer} is {@code null}.
+ * if {@code buffer == null}.
*/
@Override
- public int read(byte[] buffer, int offset, int length) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- for (int i = 0; i < length; i++) {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+ for (int i = 0; i < byteCount; ++i) {
int currentChar;
try {
currentChar = read();
@@ -182,9 +171,9 @@
if (currentChar == -1) {
return i == 0 ? -1 : i;
}
- buffer[offset + i] = (byte) currentChar;
+ buffer[byteOffset + i] = (byte) currentChar;
}
- return length;
+ return byteCount;
}
/**
diff --git a/luni/src/main/java/java/io/LineNumberReader.java b/luni/src/main/java/java/io/LineNumberReader.java
index 03d02a2..5295e77 100644
--- a/luni/src/main/java/java/io/LineNumberReader.java
+++ b/luni/src/main/java/java/io/LineNumberReader.java
@@ -132,24 +132,15 @@
}
/**
- * Reads at most {@code count} characters from the source reader and stores
+ * Reads up to {@code count} characters from the source reader and stores
* them in the character array {@code buffer} starting at {@code offset}.
* Returns the number of characters actually read or -1 if no characters
* have been read and the end of this reader has been reached.
- * <p>
- * The line number count is incremented if a line terminator is encountered.
+ *
+ * <p>The line number count is incremented if a line terminator is encountered.
* Recognized line terminator sequences are {@code '\r'}, {@code '\n'} and
* {@code "\r\n"}.
*
- * @param buffer
- * the array in which to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param count
- * the maximum number of characters to store in {@code buffer}.
- * @return the number of characters actually read or -1 if the end of the
- * source reader has been reached while reading.
* @throws IOException
* if this reader is closed or another IOException occurs.
*/
diff --git a/luni/src/main/java/java/io/ObjectInput.java b/luni/src/main/java/java/io/ObjectInput.java
index e892071..0c137c0 100644
--- a/luni/src/main/java/java/io/ObjectInput.java
+++ b/luni/src/main/java/java/io/ObjectInput.java
@@ -56,35 +56,24 @@
/**
* Reads bytes from this stream into the byte array {@code buffer}. Blocks
- * while waiting for input.
+ * while waiting for input. Returns the number of bytes read,
+ * or -1 if the end of this stream has been reached.
*
- * @param buffer
- * the array in which to store the bytes read.
- * @return the number of bytes read or -1 if the end of this stream has been
- * reached.
* @throws IOException
* if this stream is closed or another I/O error occurs.
*/
public int read(byte[] buffer) throws IOException;
/**
- * Reads at most {@code count} bytes from this stream and stores them in
- * byte array {@code buffer} starting at offset {@code count}. Blocks while
- * waiting for input.
+ * Reads up to {@code byteCount} bytes from this stream and stores them in
+ * byte array {@code buffer} starting at offset {@code byteOffset}. Blocks while
+ * waiting for input. Returns the number of bytes read or -1 if the end of this stream has been
+ * reached.
*
- * @param buffer
- * the array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes read
- * from this stream.
- * @param count
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes read or -1 if the end of this stream has been
- * reached.
* @throws IOException
* if this stream is closed or another I/O error occurs.
*/
- public int read(byte[] buffer, int offset, int count) throws IOException;
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException;
/**
* Reads the next object from this stream.
diff --git a/luni/src/main/java/java/io/ObjectInputStream.java b/luni/src/main/java/java/io/ObjectInputStream.java
index 0476901..35f6fc1 100644
--- a/luni/src/main/java/java/io/ObjectInputStream.java
+++ b/luni/src/main/java/java/io/ObjectInputStream.java
@@ -531,38 +531,13 @@
return primitiveData.read();
}
- /**
- * Reads at most {@code length} bytes from the source stream and stores them
- * in byte array {@code buffer} starting at offset {@code count}. Blocks
- * until {@code count} bytes have been read, the end of the source stream is
- * detected or an exception is thrown.
- *
- * @param buffer
- * the array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes
- * read from the source stream.
- * @param length
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes read or -1 if the end of the source input
- * stream has been reached.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code buffer}.
- * @throws IOException
- * if an error occurs while reading from this stream.
- * @throws NullPointerException
- * if {@code buffer} is {@code null}.
- */
- @Override
- public int read(byte[] buffer, int offset, int length) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- if (length == 0) {
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+ if (byteCount == 0) {
return 0;
}
checkReadPrimitiveTypes();
- return primitiveData.read(buffer, offset, length);
+ return primitiveData.read(buffer, byteOffset, byteCount);
}
/**
@@ -1404,7 +1379,7 @@
* @return the string read from the source stream.
* @throws IOException
* if an error occurs while reading from the source stream.
- * @deprecated Use {@link BufferedReader}
+ * @deprecated Use {@link BufferedReader} instead.
*/
@Deprecated
public String readLine() throws IOException {
@@ -2000,7 +1975,7 @@
// original/outside caller
if (++nestedLevels == 1) {
// Remember the caller's class loader
- callerClassLoader = getClosestUserClassLoader();
+ callerClassLoader = VMStack.getClosestUserClassLoader(bootstrapLoader, systemLoader);
}
result = readNonPrimitiveContent(unshared);
@@ -2041,23 +2016,6 @@
private static final ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
/**
- * Searches up the call stack to find the closest user-defined class loader.
- *
- * @return a user-defined class loader or null if one isn't found
- */
- private static ClassLoader getClosestUserClassLoader() {
- Class<?>[] stackClasses = VMStack.getClasses(-1);
- for (Class<?> stackClass : stackClasses) {
- ClassLoader loader = stackClass.getClassLoader();
- if (loader != null && loader != bootstrapLoader
- && loader != systemLoader) {
- return loader;
- }
- }
- return null;
- }
-
- /**
* Method to be overridden by subclasses to read the next object from the
* source stream.
*
diff --git a/luni/src/main/java/java/io/OutputStreamWriter.java b/luni/src/main/java/java/io/OutputStreamWriter.java
index 5dffdfe..d69c87a 100644
--- a/luni/src/main/java/java/io/OutputStreamWriter.java
+++ b/luni/src/main/java/java/io/OutputStreamWriter.java
@@ -225,7 +225,7 @@
}
/**
- * Returns the historical name of the encoding used by this writer to convert characters to
+ * Returns the canonical name of the encoding used by this writer to convert characters to
* bytes, or null if this writer has been closed. Most callers should probably keep
* track of the String or Charset they passed in; this method may not return the same
* name.
@@ -234,7 +234,7 @@
if (encoder == null) {
return null;
}
- return HistoricalCharsetNames.get(encoder.charset());
+ return encoder.charset().name();
}
/**
diff --git a/luni/src/main/java/java/io/PipedInputStream.java b/luni/src/main/java/java/io/PipedInputStream.java
index 739fb98..2c27695 100644
--- a/luni/src/main/java/java/io/PipedInputStream.java
+++ b/luni/src/main/java/java/io/PipedInputStream.java
@@ -256,20 +256,20 @@
}
/**
- * Reads at most {@code byteCount} bytes from this stream and stores them in the
- * byte array {@code bytes} starting at {@code offset}. Blocks until at
+ * Reads up to {@code byteCount} bytes from this stream and stores them in the
+ * byte array {@code bytes} starting at {@code byteOffset}. Blocks until at
* least one byte has been read, the end of the stream is detected or an
* exception is thrown.
- * <p>
- * Separate threads should be used to read from a {@code PipedInputStream}
+ *
+ * <p>Separate threads should be used to read from a {@code PipedInputStream}
* and to write to the connected {@link PipedOutputStream}. If the same
* thread is used, a deadlock may occur.
*
- * @return the number of bytes actually read or -1 if the end of the stream
- * has been reached.
+ * <p>Returns the number of bytes actually read or -1 if the end of the stream
+ * has been reached.
+ *
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code byteCount < 0}, or if {@code
- * offset + byteCount} is greater than the size of {@code bytes}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > bytes.length}.
* @throws InterruptedIOException
* if the thread reading from this stream is interrupted.
* @throws IOException
@@ -279,9 +279,8 @@
* @throws NullPointerException
* if {@code bytes} is {@code null}.
*/
- @Override
- public synchronized int read(byte[] bytes, int offset, int byteCount) throws IOException {
- Arrays.checkOffsetAndCount(bytes.length, offset, byteCount);
+ @Override public synchronized int read(byte[] bytes, int byteOffset, int byteCount) throws IOException {
+ Arrays.checkOffsetAndCount(bytes.length, byteOffset, byteCount);
if (byteCount == 0) {
return 0;
}
@@ -324,7 +323,7 @@
if (out >= in) {
int leftInBuffer = buffer.length - out;
int length = leftInBuffer < byteCount ? leftInBuffer : byteCount;
- System.arraycopy(buffer, out, bytes, offset, length);
+ System.arraycopy(buffer, out, bytes, byteOffset, length);
out += length;
if (out == buffer.length) {
out = 0;
@@ -342,7 +341,7 @@
int leftInBuffer = in - out;
int leftToCopy = byteCount - totalCopied;
int length = leftToCopy < leftInBuffer ? leftToCopy : leftInBuffer;
- System.arraycopy(buffer, out, bytes, offset + totalCopied, length);
+ System.arraycopy(buffer, out, bytes, byteOffset + totalCopied, length);
out += length;
if (out == in) {
// empty buffer
diff --git a/luni/src/main/java/java/io/PipedReader.java b/luni/src/main/java/java/io/PipedReader.java
index 8450a34..908505d 100644
--- a/luni/src/main/java/java/io/PipedReader.java
+++ b/luni/src/main/java/java/io/PipedReader.java
@@ -199,28 +199,21 @@
}
/**
- * Reads at most {@code count} characters from this reader and stores them
+ * Reads up to {@code count} characters from this reader and stores them
* in the character array {@code buffer} starting at {@code offset}. If
* there is no data in the pipe, this method blocks until at least one byte
* has been read, the end of the reader is detected or an exception is
* thrown.
- * <p>
- * Separate threads should be used to read from a {@code PipedReader} and to
+ *
+ * <p>Separate threads should be used to read from a {@code PipedReader} and to
* write to the connected {@link PipedWriter}. If the same thread is used, a
* deadlock may occur.
*
- * @param buffer
- * the character array in which to store the characters read.
- * @param offset
- * the initial position in {@code bytes} to store the characters
- * read from this reader.
- * @param count
- * the maximum number of characters to store in {@code buffer}.
- * @return the number of characters read or -1 if the end of the reader has
- * been reached.
+ * <p>Returns the number of characters read or -1 if the end of the reader has
+ * been reached.
+ *
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code count < 0}, or if {@code
- * offset + count} is greater than the size of {@code buffer}.
+ * if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
* @throws InterruptedIOException
* if the thread reading from this reader is interrupted.
* @throws IOException
@@ -228,8 +221,7 @@
* the thread writing to the connected writer is no longer
* alive.
*/
- @Override
- public synchronized int read(char[] buffer, int offset, int count) throws IOException {
+ @Override public synchronized int read(char[] buffer, int offset, int count) throws IOException {
if (!isConnected) {
throw new IOException("Pipe not connected");
}
diff --git a/luni/src/main/java/java/io/PushbackInputStream.java b/luni/src/main/java/java/io/PushbackInputStream.java
index fa0df85..d7bebb1 100644
--- a/luni/src/main/java/java/io/PushbackInputStream.java
+++ b/luni/src/main/java/java/io/PushbackInputStream.java
@@ -147,42 +147,31 @@
}
/**
- * Reads at most {@code length} bytes from this stream and stores them in
- * the byte array {@code buffer} starting at {@code offset}. Bytes are read
+ * Reads up to {@code byteCount} bytes from this stream and stores them in
+ * the byte array {@code buffer} starting at {@code byteOffset}. Bytes are read
* from the pushback buffer first, then from the source stream if more bytes
- * are required. Blocks until {@code count} bytes have been read, the end of
- * the source stream is detected or an exception is thrown.
+ * are required. Blocks until {@code byteCount} bytes have been read, the end of
+ * the source stream is detected or an exception is thrown. Returns the number of bytes read,
+ * or -1 if the end of the source stream has been reached.
*
- * @param buffer
- * the array in which to store the bytes read from this stream.
- * @param offset
- * the initial position in {@code buffer} to store the bytes read
- * from this stream.
- * @param length
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes read or -1 if the end of the source stream
- * has been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code buffer}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
* @throws IOException
* if this stream is closed or another I/O error occurs while
* reading from this stream.
* @throws NullPointerException
- * if {@code buffer} is {@code null}.
+ * if {@code buffer == null}.
*/
@Override
- public int read(byte[] buffer, int offset, int length) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (buf == null) {
throw streamClosed();
}
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- int copiedBytes = 0, copyLength = 0, newOffset = offset;
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+ int copiedBytes = 0, copyLength = 0, newOffset = byteOffset;
// Are there pushback bytes available?
if (pos < buf.length) {
- copyLength = (buf.length - pos >= length) ? length : buf.length
- - pos;
+ copyLength = (buf.length - pos >= byteCount) ? byteCount : buf.length - pos;
System.arraycopy(buf, pos, buffer, newOffset, copyLength);
newOffset += copyLength;
copiedBytes += copyLength;
@@ -190,10 +179,10 @@
pos += copyLength;
}
// Have we copied enough?
- if (copyLength == length) {
- return length;
+ if (copyLength == byteCount) {
+ return byteCount;
}
- int inCopied = in.read(buffer, newOffset, length - copiedBytes);
+ int inCopied = in.read(buffer, newOffset, byteCount - copiedBytes);
if (inCopied > 0) {
return inCopied + copiedBytes;
}
diff --git a/luni/src/main/java/java/io/PushbackReader.java b/luni/src/main/java/java/io/PushbackReader.java
index 2e3cf83..59e6644 100644
--- a/luni/src/main/java/java/io/PushbackReader.java
+++ b/luni/src/main/java/java/io/PushbackReader.java
@@ -155,26 +155,15 @@
}
/**
- * Reads at most {@code length} bytes from this reader and stores them in
- * byte array {@code buffer} starting at {@code offset}. Characters are
+ * Reads up to {@code count} characters from this reader and stores them in
+ * character array {@code buffer} starting at {@code offset}. Characters are
* read from the pushback buffer first, then from the source reader if more
* bytes are required. Blocks until {@code count} characters have been read,
* the end of the source reader is detected or an exception is thrown.
+ * Returns the number of bytes read or -1 if the end of the source reader has been reached.
*
- * @param buffer
- * the array in which to store the characters read from this
- * reader.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param count
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes read or -1 if the end of the source reader
- * has been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code count < 0}, or if
- * {@code offset + count} is greater than the length of
- * {@code buffer}.
+ * if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
* @throws IOException
* if this reader is closed or another I/O error occurs while
* reading from this reader.
diff --git a/luni/src/main/java/java/io/RandomAccessFile.java b/luni/src/main/java/java/io/RandomAccessFile.java
index dde779e..a60da3e 100644
--- a/luni/src/main/java/java/io/RandomAccessFile.java
+++ b/luni/src/main/java/java/io/RandomAccessFile.java
@@ -260,11 +260,9 @@
* byte array {@code buffer}. The maximum number of bytes read corresponds
* to the size of {@code buffer}. Blocks until at least one byte has been
* read, the end of the file is detected, or an exception is thrown.
+ * Returns the number of bytes actually read or -1 if the end of the file
+ * has been reached. See also {@link #readFully}.
*
- * @param buffer
- * the byte array in which to store the bytes read.
- * @return the number of bytes actually read or -1 if the end of the file
- * has been reached.
* @throws IOException
* if this file is closed or another I/O error occurs.
*/
@@ -273,16 +271,15 @@
}
/**
- * Reads at most {@code byteCount} bytes from the current position in this file
+ * Reads up to {@code byteCount} bytes from the current position in this file
* and stores them in the byte array {@code buffer} starting at {@code
* byteOffset}. Blocks until at least one byte has been
* read, the end of the file is detected, or an exception is thrown.
+ * Returns the number of bytes actually read or -1 if the end of the stream has been reached.
+ * See also {@link #readFully}.
*
- * @return the number of bytes actually read or -1 if the end of the stream
- * has been reached.
* @throws IndexOutOfBoundsException
- * if {@code byteOffset < 0} or {@code byteCount < 0}, or if {@code
- * byteOffset + byteCount} is greater than the size of {@code buffer}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
* @throws IOException
* if this file is closed or another I/O error occurs.
*/
diff --git a/luni/src/main/java/java/io/Reader.java b/luni/src/main/java/java/io/Reader.java
index e947d08..8ef9a7c 100644
--- a/luni/src/main/java/java/io/Reader.java
+++ b/luni/src/main/java/java/io/Reader.java
@@ -131,39 +131,26 @@
/**
* Reads characters from this reader and stores them in the character array
- * {@code buf} starting at offset 0. Returns the number of characters
+ * {@code buffer} starting at offset 0. Returns the number of characters
* actually read or -1 if the end of the reader has been reached.
*
- * @param buf
- * character array to store the characters read.
- * @return the number of characters read or -1 if the end of the reader has
- * been reached.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/
- public int read(char[] buf) throws IOException {
- return read(buf, 0, buf.length);
+ public int read(char[] buffer) throws IOException {
+ return read(buffer, 0, buffer.length);
}
/**
- * Reads at most {@code count} characters from this reader and stores them
- * at {@code offset} in the character array {@code buf}. Returns the number
+ * Reads up to {@code count} characters from this reader and stores them
+ * at {@code offset} in the character array {@code buffer}. Returns the number
* of characters actually read or -1 if the end of the reader has been
* reached.
*
- * @param buf
- * the character array to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param count
- * the maximum number of characters to read.
- * @return the number of characters read or -1 if the end of the reader has
- * been reached.
* @throws IOException
* if this reader is closed or some other I/O error occurs.
*/
- public abstract int read(char[] buf, int offset, int count) throws IOException;
+ public abstract int read(char[] buffer, int offset, int count) throws IOException;
/**
* Indicates whether this reader is ready to be read without blocking.
diff --git a/luni/src/main/java/java/io/SequenceInputStream.java b/luni/src/main/java/java/io/SequenceInputStream.java
index 8333834..a328167 100644
--- a/luni/src/main/java/java/io/SequenceInputStream.java
+++ b/luni/src/main/java/java/io/SequenceInputStream.java
@@ -146,15 +146,15 @@
}
/**
- * Reads at most {@code count} bytes from this sequence of input streams and
- * stores them in the byte array {@code buffer} starting at {@code offset}.
+ * Reads up to {@code byteCount} bytes from this sequence of input streams and
+ * stores them in the byte array {@code buffer} starting at {@code byteOffset}.
* Blocks only until at least 1 byte has been read, the end of the stream
* has been reached, or an exception is thrown.
* <p>
* This SequenceInputStream shows the same behavior as other InputStreams.
* To do this it will read only as many bytes as a call to read on the
* current substream returns. If that call does not return as many bytes as
- * requested by {@code count}, it will not retry to read more on its own
+ * requested by {@code byteCount}, it will not retry to read more on its own
* because subsequent reads might block. This would violate the rule that
* it will only block until at least one byte has been read.
* <p>
@@ -162,32 +162,21 @@
* will close that substream and start with the next one. If there are no
* more substreams it will return -1.
*
- * @param buffer
- * the array in which to store the bytes read.
- * @param offset
- * the initial position in {@code buffer} to store the bytes read
- * from this stream.
- * @param count
- * the maximum number of bytes to store in {@code buffer}.
- * @return the number of bytes actually read; -1 if this sequence of streams
- * is closed or if the end of the last stream in the sequence has
- * been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code count < 0}, or if {@code
- * offset + count} is greater than the size of {@code buffer}.
+ * if {@code byteOffset < 0 || byteCount < 0 || byteOffset + byteCount > buffer.length}.
* @throws IOException
* if an I/O error occurs.
* @throws NullPointerException
- * if {@code buffer} is {@code null}.
+ * if {@code buffer == null}.
*/
@Override
- public int read(byte[] buffer, int offset, int count) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (in == null) {
return -1;
}
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
while (in != null) {
- int result = in.read(buffer, offset, count);
+ int result = in.read(buffer, byteOffset, byteCount);
if (result >= 0) {
return result;
}
diff --git a/luni/src/main/java/java/io/StreamTokenizer.java b/luni/src/main/java/java/io/StreamTokenizer.java
index a16dc4b..a9e5373 100644
--- a/luni/src/main/java/java/io/StreamTokenizer.java
+++ b/luni/src/main/java/java/io/StreamTokenizer.java
@@ -155,13 +155,13 @@
/**
* Constructs a new {@code StreamTokenizer} with {@code is} as source input
* stream. This constructor is deprecated; instead, the constructor that
- * takes a {@code Reader} as an arugment should be used.
+ * takes a {@code Reader} as an argument should be used.
*
* @param is
* the source stream from which to parse tokens.
* @throws NullPointerException
* if {@code is} is {@code null}.
- * @deprecated Use {@link #StreamTokenizer(Reader)}
+ * @deprecated Use {@link #StreamTokenizer(Reader)} instead.
*/
@Deprecated
public StreamTokenizer(InputStream is) {
diff --git a/luni/src/main/java/java/io/StringBufferInputStream.java b/luni/src/main/java/java/io/StringBufferInputStream.java
index 1768abe..fb3fb73 100644
--- a/luni/src/main/java/java/io/StringBufferInputStream.java
+++ b/luni/src/main/java/java/io/StringBufferInputStream.java
@@ -23,7 +23,7 @@
* A specialized {@link InputStream} that reads bytes from a {@code String} in
* a sequential manner.
*
- * @deprecated Use {@link StringReader}
+ * @deprecated Use {@link StringReader} instead.
*/
@Deprecated
public class StringBufferInputStream extends InputStream {
@@ -78,39 +78,18 @@
return pos < count ? buffer.charAt(pos++) & 0xFF : -1;
}
- /**
- * Reads at most {@code length} bytes from the source string and stores them
- * in the byte array {@code b} starting at {@code offset}.
- *
- * @param buffer
- * the byte array in which to store the bytes read.
- * @param offset
- * the initial position in {@code b} to store the bytes read from
- * this stream.
- * @param length
- * the maximum number of bytes to store in {@code b}.
- * @return the number of bytes actually read or -1 if the end of the source
- * string has been reached.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code length < 0}, or if
- * {@code offset + length} is greater than the length of
- * {@code b}.
- * @throws NullPointerException
- * if {@code b} is {@code null}.
- */
- @Override
- public synchronized int read(byte[] buffer, int offset, int length) {
+ @Override public synchronized int read(byte[] buffer, int byteOffset, int byteCount) {
if (buffer == null) {
throw new NullPointerException("buffer == null");
}
- Arrays.checkOffsetAndCount(buffer.length, offset, length);
- if (length == 0) {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
+ if (byteCount == 0) {
return 0;
}
- int copylen = count - pos < length ? count - pos : length;
- for (int i = 0; i < copylen; i++) {
- buffer[offset + i] = (byte) this.buffer.charAt(pos + i);
+ int copylen = count - pos < byteCount ? count - pos : byteCount;
+ for (int i = 0; i < copylen; ++i) {
+ buffer[byteOffset + i] = (byte) this.buffer.charAt(pos + i);
}
pos += copylen;
return copylen;
diff --git a/luni/src/main/java/java/io/StringReader.java b/luni/src/main/java/java/io/StringReader.java
index 5579d62..ebe6c83 100644
--- a/luni/src/main/java/java/io/StringReader.java
+++ b/luni/src/main/java/java/io/StringReader.java
@@ -131,39 +131,29 @@
}
/**
- * Reads at most {@code len} characters from the source string and stores
- * them at {@code offset} in the character array {@code buf}. Returns the
+ * Reads up to {@code count} characters from the source string and stores
+ * them at {@code offset} in the character array {@code buffer}. Returns the
* number of characters actually read or -1 if the end of the source string
* has been reached.
*
- * @param buf
- * the character array to store the characters read.
- * @param offset
- * the initial position in {@code buffer} to store the characters
- * read from this reader.
- * @param len
- * the maximum number of characters to read.
- * @return the number of characters read or -1 if the end of the reader has
- * been reached.
* @throws IndexOutOfBoundsException
- * if {@code offset < 0} or {@code len < 0}, or if
- * {@code offset + len} is greater than the size of {@code buf}.
+ if {@code offset < 0 || count < 0 || offset + count > buffer.length}.
* @throws IOException
* if this reader is closed.
*/
@Override
- public int read(char[] buf, int offset, int len) throws IOException {
+ public int read(char[] buffer, int offset, int count) throws IOException {
synchronized (lock) {
checkNotClosed();
- Arrays.checkOffsetAndCount(buf.length, offset, len);
- if (len == 0) {
+ Arrays.checkOffsetAndCount(buffer.length, offset, count);
+ if (count == 0) {
return 0;
}
if (pos == this.count) {
return -1;
}
- int end = pos + len > this.count ? this.count : pos + len;
- str.getChars(pos, end, buf, offset);
+ int end = pos + count > this.count ? this.count : pos + count;
+ str.getChars(pos, end, buffer, offset);
int read = end - pos;
pos = end;
return read;
diff --git a/luni/src/main/java/java/lang/AssertionError.java b/luni/src/main/java/java/lang/AssertionError.java
index 077e57c..e00d8e6 100644
--- a/luni/src/main/java/java/lang/AssertionError.java
+++ b/luni/src/main/java/java/lang/AssertionError.java
@@ -35,7 +35,6 @@
/**
* Constructs a new {@code AssertionError} with the given detail message and cause.
* @since 1.7
- * @hide 1.7
*/
public AssertionError(String detailMessage, Throwable cause) {
super(detailMessage, cause);
diff --git a/luni/src/main/java/java/lang/AutoCloseable.java b/luni/src/main/java/java/lang/AutoCloseable.java
index b3133a9..df789e0 100644
--- a/luni/src/main/java/java/lang/AutoCloseable.java
+++ b/luni/src/main/java/java/lang/AutoCloseable.java
@@ -31,15 +31,10 @@
* }</pre>
*
* @since 1.7
- * @hide 1.7
*/
public interface AutoCloseable {
-
/**
* Closes the object and release any system resources it holds.
- *
- * <p>Unless the implementing class specifies otherwise, it is an error to
- * call {@link #close} more than once.
*/
void close() throws Exception;
}
diff --git a/luni/src/main/java/java/lang/Boolean.java b/luni/src/main/java/java/lang/Boolean.java
index 2c8ffc8..fb02093 100644
--- a/luni/src/main/java/java/lang/Boolean.java
+++ b/luni/src/main/java/java/lang/Boolean.java
@@ -129,7 +129,6 @@
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* (Where true > false.)
* @since 1.7
- * @hide 1.7
*/
public static int compare(boolean lhs, boolean rhs) {
return lhs == rhs ? 0 : lhs ? 1 : -1;
diff --git a/luni/src/main/java/java/lang/Byte.java b/luni/src/main/java/java/lang/Byte.java
index bd1a1e4..0ea50bf 100644
--- a/luni/src/main/java/java/lang/Byte.java
+++ b/luni/src/main/java/java/lang/Byte.java
@@ -113,7 +113,6 @@
* Compares two {@code byte} values.
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* @since 1.7
- * @hide 1.7
*/
public static int compare(byte lhs, byte rhs) {
return lhs > rhs ? 1 : (lhs < rhs ? -1 : 0);
diff --git a/luni/src/main/java/java/lang/Character.java b/luni/src/main/java/java/lang/Character.java
index cf0ab84..5762bd4 100644
--- a/luni/src/main/java/java/lang/Character.java
+++ b/luni/src/main/java/java/lang/Character.java
@@ -522,66 +522,51 @@
* Represents a subset of the Unicode character set.
*/
public static class Subset {
- String name;
+ private final String name;
/**
* Constructs a new {@code Subset}.
- *
- * @param string
- * this subset's name.
*/
- protected Subset(String string) {
- if (string == null) {
- throw new NullPointerException("string == null");
+ protected Subset(String name) {
+ if (name == null) {
+ throw new NullPointerException("name == null");
}
- name = string;
+ this.name = name;
}
/**
- * Compares this character subset with the specified object. Uses
- * {@link java.lang.Object#equals(Object)} to do the comparison.
- *
- * @param object
- * the object to compare this character subset with.
- * @return {@code true} if {@code object} is this subset, that is, if
- * {@code object == this}; {@code false} otherwise.
+ * Compares this character subset for identity with the specified object.
*/
- @Override
- public final boolean equals(Object object) {
- return super.equals(object);
+ @Override public final boolean equals(Object object) {
+ return object == this;
}
/**
- * Returns the integer hash code for this character subset.
- *
- * @return this subset's hash code, which is the hash code computed by
+ * Returns this subset's hash code, which is the hash code computed by
* {@link java.lang.Object#hashCode()}.
*/
- @Override
- public final int hashCode() {
+ @Override public final int hashCode() {
return super.hashCode();
}
/**
- * Returns the string representation of this subset.
- *
- * @return this subset's name.
+ * Returns this subset's name.
*/
- @Override
- public final String toString() {
+ @Override public final String toString() {
return name;
}
}
/**
- * Represents a block of Unicode characters, as defined by the Unicode 4.0.1
- * specification.
+ * Represents a block of Unicode characters. This class provides constants for various
+ * well-known blocks (but not all blocks) and methods for looking up a block
+ * by name {@link #forName} or by code point {@link #of}.
*
* @since 1.2
*/
public static final class UnicodeBlock extends Subset {
/**
- * The "Surrogates Area" Unicode Block.
+ * The Surrogates Area Unicode block.
*
* @deprecated As of Java 5, this block has been replaced by
* {@link #HIGH_SURROGATES},
@@ -589,765 +574,669 @@
* {@link #LOW_SURROGATES}.
*/
@Deprecated
- public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA", 0x0, 0x0);
+ public static final UnicodeBlock SURROGATES_AREA = new UnicodeBlock("SURROGATES_AREA");
+
+ /** The Basic Latin Unicode block. */
+ public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN");
+
+ /** The Latin-1 Supplement Unicode block. */
+ public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT");
+
+ /** The Latin Extended-A Unicode block. */
+ public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A");
+
+ /** The Latin Extended-B Unicode block. */
+ public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B");
+
+ /** The IPA Extensions Unicode block. */
+ public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS");
+
+ /** The Spacing Modifier Letters Unicode block. */
+ public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS");
+
+ /** The Combining Diacritical Marks Unicode block. */
+ public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS");
+
/**
- * The "Basic Latin" Unicode Block.
- *
- * @since 1.2
+ * The Greek and Coptic Unicode block. Previously referred to as Greek.
*/
- public static final UnicodeBlock BASIC_LATIN = new UnicodeBlock("BASIC_LATIN", 0x0, 0x7f);
+ public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK");
+
+ /** The Cyrillic Unicode block. */
+ public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC");
+
/**
- * The "Latin-1 Supplement" Unicode Block.
- *
- * @since 1.2
+ * The Cyrillic Supplement Unicode block. Previously referred to as Cyrillic Supplementary.
*/
- public static final UnicodeBlock LATIN_1_SUPPLEMENT = new UnicodeBlock("LATIN_1_SUPPLEMENT", 0x80, 0xff);
+ public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY");
+
+ /** The Armenian Unicode block. */
+ public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN");
+
+ /** The Hebrew Unicode block. */
+ public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW");
+
+ /** The Arabic Unicode block. */
+ public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC");
+
+ /** The Syriac Unicode block. */
+ public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC");
+
+ /** The Thaana Unicode block. */
+ public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA");
+
+ /** The Devanagari Unicode block. */
+ public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI");
+
+ /** The Bengali Unicode block. */
+ public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI");
+
+ /** The Gurmukhi Unicode block. */
+ public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI");
+
+ /** The Gujarati Unicode block. */
+ public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI");
+
+ /** The Oriya Unicode block. */
+ public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA");
+
+ /** The Tamil Unicode block. */
+ public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL");
+
+ /** The Telugu Unicode block. */
+ public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU");
+
+ /** The Kannada Unicode block. */
+ public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA");
+
+ /** The Malayalam Unicode block. */
+ public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM");
+
+ /** The Sinhala Unicode block. */
+ public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA");
+
+ /** The Thai Unicode block. */
+ public static final UnicodeBlock THAI = new UnicodeBlock("THAI");
+
+ /** The Lao Unicode block. */
+ public static final UnicodeBlock LAO = new UnicodeBlock("LAO");
+
+ /** The Tibetan Unicode block. */
+ public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN");
+
+ /** The Myanmar Unicode block. */
+ public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR");
+
+ /** The Georgian Unicode block. */
+ public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN");
+
+ /** The Hangul Jamo Unicode block. */
+ public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO");
+
+ /** The Ethiopic Unicode block. */
+ public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC");
+
+ /** The Cherokee Unicode block. */
+ public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE");
+
+ /** The Unified Canadian Aboriginal Syllabics Unicode block. */
+ public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS");
+
+ /** The Ogham Unicode block. */
+ public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM");
+
+ /** The Runic Unicode block. */
+ public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC");
+
+ /** The Tagalog Unicode block. */
+ public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG");
+
+ /** The Hanunoo Unicode block. */
+ public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO");
+
+ /** The Buhid Unicode block. */
+ public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID");
+
+ /** The Tagbanwa Unicode block. */
+ public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA");
+
+ /** The Khmer Unicode block. */
+ public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER");
+
+ /** The Mongolian Unicode block. */
+ public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN");
+
+ /** The Limbu Unicode block. */
+ public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU");
+
+ /** The Tai Le Unicode block. */
+ public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE");
+
+ /** The Khmer Symbols Unicode block. */
+ public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS");
+
+ /** The Phonetic Extensions Unicode block. */
+ public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS");
+
+ /** The Latin Extended Additional Unicode block. */
+ public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL");
+
+ /** The Greek Extended Unicode block. */
+ public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED");
+
+ /** The General Punctuation Unicode block. */
+ public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION");
+
+ /** The Superscripts and Subscripts Unicode block. */
+ public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS");
+
+ /** The Currency Symbols Unicode block. */
+ public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS");
+
/**
- * The "Latin Extended-A" Unicode Block.
- *
- * @since 1.2
+ * The Combining Diacritical Marks for Symbols Unicode
+ * Block. Previously referred to as Combining Marks for
+ * Symbols.
*/
- public static final UnicodeBlock LATIN_EXTENDED_A = new UnicodeBlock("LATIN_EXTENDED_A", 0x100, 0x17f);
+ public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS");
+
+ /** The Letterlike Symbols Unicode block. */
+ public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS");
+
+ /** The Number Forms Unicode block. */
+ public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS");
+
+ /** The Arrows Unicode block. */
+ public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS");
+
+ /** The Mathematical Operators Unicode block. */
+ public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS");
+
+ /** The Miscellaneous Technical Unicode block. */
+ public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL");
+
+ /** The Control Pictures Unicode block. */
+ public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES");
+
+ /** The Optical Character Recognition Unicode block. */
+ public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION");
+
+ /** The Enclosed Alphanumerics Unicode block. */
+ public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS");
+
+ /** The Box Drawing Unicode block. */
+ public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING");
+
+ /** The Block Elements Unicode block. */
+ public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS");
+
+ /** The Geometric Shapes Unicode block. */
+ public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES");
+
+ /** The Miscellaneous Symbols Unicode block. */
+ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS");
+
+ /** The Dingbats Unicode block. */
+ public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS");
+
+ /** The Miscellaneous Mathematical Symbols-A Unicode block. */
+ public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A");
+
+ /** The Supplemental Arrows-A Unicode block. */
+ public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A");
+
+ /** The Braille Patterns Unicode block. */
+ public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS");
+
+ /** The Supplemental Arrows-B Unicode block. */
+ public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B");
+
+ /** The Miscellaneous Mathematical Symbols-B Unicode block. */
+ public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B");
+
+ /** The Supplemental Mathematical Operators Unicode block. */
+ public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS");
+
+ /** The Miscellaneous Symbols and Arrows Unicode block. */
+ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS");
+
+ /** The CJK Radicals Supplement Unicode block. */
+ public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT");
+
+ /** The Kangxi Radicals Unicode block. */
+ public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS");
+
+ /** The Ideographic Description Characters Unicode block. */
+ public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS");
+
+ /** The CJK Symbols and Punctuation Unicode block. */
+ public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION");
+
+ /** The Hiragana Unicode block. */
+ public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA");
+
+ /** The Katakana Unicode block. */
+ public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA");
+
+ /** The Bopomofo Unicode block. */
+ public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO");
+
+ /** The Hangul Compatibility Jamo Unicode block. */
+ public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO");
+
+ /** The Kanbun Unicode block. */
+ public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN");
+
+ /** The Bopomofo Extended Unicode block. */
+ public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED");
+
+ /** The Katakana Phonetic Extensions Unicode block. */
+ public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS");
+
+ /** The Enclosed CJK Letters and Months Unicode block. */
+ public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS");
+
+ /** The CJK Compatibility Unicode block. */
+ public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY");
+
+ /** The CJK Unified Ideographs Extension A Unicode block. */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A");
+
+ /** The Yijing Hexagram Symbols Unicode block. */
+ public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS");
+
+ /** The CJK Unified Ideographs Unicode block. */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS");
+
+ /** The Yi Syllables Unicode block. */
+ public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES");
+
+ /** The Yi Radicals Unicode block. */
+ public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS");
+
+ /** The Hangul Syllables Unicode block. */
+ public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES");
+
/**
- * The "Latin Extended-B" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock LATIN_EXTENDED_B = new UnicodeBlock("LATIN_EXTENDED_B", 0x180, 0x24f);
- /**
- * The "IPA Extensions" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock IPA_EXTENSIONS = new UnicodeBlock("IPA_EXTENSIONS", 0x250, 0x2af);
- /**
- * The "Spacing Modifier Letters" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock SPACING_MODIFIER_LETTERS = new UnicodeBlock("SPACING_MODIFIER_LETTERS", 0x2b0, 0x2ff);
- /**
- * The "Combining Diacritical Marks" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS", 0x300, 0x36f);
- /**
- * The "Greek and Coptic" Unicode Block. Previously referred
- * to as "Greek".
- *
- * @since 1.2
- */
- public static final UnicodeBlock GREEK = new UnicodeBlock("GREEK", 0x370, 0x3ff);
- /**
- * The "Cyrillic" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CYRILLIC = new UnicodeBlock("CYRILLIC", 0x400, 0x4ff);
- /**
- * The "Cyrillic Supplement" Unicode Block. Previously
- * referred to as "Cyrillic Supplementary".
- *
- * @since 1.5
- */
- public static final UnicodeBlock CYRILLIC_SUPPLEMENTARY = new UnicodeBlock("CYRILLIC_SUPPLEMENTARY", 0x500, 0x52f);
- /**
- * The "Armenian" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ARMENIAN = new UnicodeBlock("ARMENIAN", 0x530, 0x58f);
- /**
- * The "Hebrew" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HEBREW = new UnicodeBlock("HEBREW", 0x590, 0x5ff);
- /**
- * The "Arabic" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ARABIC = new UnicodeBlock("ARABIC", 0x600, 0x6ff);
- /**
- * The "Syriac" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock SYRIAC = new UnicodeBlock("SYRIAC", 0x700, 0x74f);
- /**
- * The "Thaana" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock THAANA = new UnicodeBlock("THAANA", 0x780, 0x7bf);
- /**
- * The "Devanagari" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock DEVANAGARI = new UnicodeBlock("DEVANAGARI", 0x900, 0x97f);
- /**
- * The "Bengali" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock BENGALI = new UnicodeBlock("BENGALI", 0x980, 0x9ff);
- /**
- * The "Gurmukhi" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GURMUKHI = new UnicodeBlock("GURMUKHI", 0xa00, 0xa7f);
- /**
- * The "Gujarati" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GUJARATI = new UnicodeBlock("GUJARATI", 0xa80, 0xaff);
- /**
- * The "Oriya" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ORIYA = new UnicodeBlock("ORIYA", 0xb00, 0xb7f);
- /**
- * The "Tamil" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock TAMIL = new UnicodeBlock("TAMIL", 0xb80, 0xbff);
- /**
- * The "Telugu" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock TELUGU = new UnicodeBlock("TELUGU", 0xc00, 0xc7f);
- /**
- * The "Kannada" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock KANNADA = new UnicodeBlock("KANNADA", 0xc80, 0xcff);
- /**
- * The "Malayalam" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock MALAYALAM = new UnicodeBlock("MALAYALAM", 0xd00, 0xd7f);
- /**
- * The "Sinhala" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock SINHALA = new UnicodeBlock("SINHALA", 0xd80, 0xdff);
- /**
- * The "Thai" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock THAI = new UnicodeBlock("THAI", 0xe00, 0xe7f);
- /**
- * The "Lao" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock LAO = new UnicodeBlock("LAO", 0xe80, 0xeff);
- /**
- * The "Tibetan" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock TIBETAN = new UnicodeBlock("TIBETAN", 0xf00, 0xfff);
- /**
- * The "Myanmar" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock MYANMAR = new UnicodeBlock("MYANMAR", 0x1000, 0x109f);
- /**
- * The "Georgian" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GEORGIAN = new UnicodeBlock("GEORGIAN", 0x10a0, 0x10ff);
- /**
- * The "Hangul Jamo" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HANGUL_JAMO = new UnicodeBlock("HANGUL_JAMO", 0x1100, 0x11ff);
- /**
- * The "Ethiopic" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock ETHIOPIC = new UnicodeBlock("ETHIOPIC", 0x1200, 0x137f);
- /**
- * The "Cherokee" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock CHEROKEE = new UnicodeBlock("CHEROKEE", 0x13a0, 0x13ff);
- /**
- * The "Unified Canadian Aboriginal Syllabics" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS", 0x1400, 0x167f);
- /**
- * The "Ogham" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock OGHAM = new UnicodeBlock("OGHAM", 0x1680, 0x169f);
- /**
- * The "Runic" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock RUNIC = new UnicodeBlock("RUNIC", 0x16a0, 0x16ff);
- /**
- * The "Tagalog" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock TAGALOG = new UnicodeBlock("TAGALOG", 0x1700, 0x171f);
- /**
- * The "Hanunoo" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock HANUNOO = new UnicodeBlock("HANUNOO", 0x1720, 0x173f);
- /**
- * The "Buhid" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock BUHID = new UnicodeBlock("BUHID", 0x1740, 0x175f);
- /**
- * The "Tagbanwa" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock TAGBANWA = new UnicodeBlock("TAGBANWA", 0x1760, 0x177f);
- /**
- * The "Khmer" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock KHMER = new UnicodeBlock("KHMER", 0x1780, 0x17ff);
- /**
- * The "Mongolian" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock MONGOLIAN = new UnicodeBlock("MONGOLIAN", 0x1800, 0x18af);
- /**
- * The "Limbu" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock LIMBU = new UnicodeBlock("LIMBU", 0x1900, 0x194f);
- /**
- * The "Tai Le" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock TAI_LE = new UnicodeBlock("TAI_LE", 0x1950, 0x197f);
- /**
- * The "Khmer Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock KHMER_SYMBOLS = new UnicodeBlock("KHMER_SYMBOLS", 0x19e0, 0x19ff);
- /**
- * The "Phonetic Extensions" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock PHONETIC_EXTENSIONS = new UnicodeBlock("PHONETIC_EXTENSIONS", 0x1d00, 0x1d7f);
- /**
- * The "Latin Extended Additional" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock LATIN_EXTENDED_ADDITIONAL = new UnicodeBlock("LATIN_EXTENDED_ADDITIONAL", 0x1e00, 0x1eff);
- /**
- * The "Greek Extended" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GREEK_EXTENDED = new UnicodeBlock("GREEK_EXTENDED", 0x1f00, 0x1fff);
- /**
- * The "General Punctuation" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GENERAL_PUNCTUATION = new UnicodeBlock("GENERAL_PUNCTUATION", 0x2000, 0x206f);
- /**
- * The "Superscripts and Subscripts" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock SUPERSCRIPTS_AND_SUBSCRIPTS = new UnicodeBlock("SUPERSCRIPTS_AND_SUBSCRIPTS", 0x2070, 0x209f);
- /**
- * The "Currency Symbols" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CURRENCY_SYMBOLS = new UnicodeBlock("CURRENCY_SYMBOLS", 0x20a0, 0x20cf);
- /**
- * The "Combining Diacritical Marks for Symbols" Unicode
- * Block. Previously referred to as "Combining Marks for
- * Symbols".
- *
- * @since 1.2
- */
- public static final UnicodeBlock COMBINING_MARKS_FOR_SYMBOLS = new UnicodeBlock("COMBINING_MARKS_FOR_SYMBOLS", 0x20d0, 0x20ff);
- /**
- * The "Letterlike Symbols" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock LETTERLIKE_SYMBOLS = new UnicodeBlock("LETTERLIKE_SYMBOLS", 0x2100, 0x214f);
- /**
- * The "Number Forms" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock NUMBER_FORMS = new UnicodeBlock("NUMBER_FORMS", 0x2150, 0x218f);
- /**
- * The "Arrows" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ARROWS = new UnicodeBlock("ARROWS", 0x2190, 0x21ff);
- /**
- * The "Mathematical Operators" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock MATHEMATICAL_OPERATORS = new UnicodeBlock("MATHEMATICAL_OPERATORS", 0x2200, 0x22ff);
- /**
- * The "Miscellaneous Technical" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock MISCELLANEOUS_TECHNICAL = new UnicodeBlock("MISCELLANEOUS_TECHNICAL", 0x2300, 0x23ff);
- /**
- * The "Control Pictures" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CONTROL_PICTURES = new UnicodeBlock("CONTROL_PICTURES", 0x2400, 0x243f);
- /**
- * The "Optical Character Recognition" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock OPTICAL_CHARACTER_RECOGNITION = new UnicodeBlock("OPTICAL_CHARACTER_RECOGNITION", 0x2440, 0x245f);
- /**
- * The "Enclosed Alphanumerics" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ENCLOSED_ALPHANUMERICS = new UnicodeBlock("ENCLOSED_ALPHANUMERICS", 0x2460, 0x24ff);
- /**
- * The "Box Drawing" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock BOX_DRAWING = new UnicodeBlock("BOX_DRAWING", 0x2500, 0x257f);
- /**
- * The "Block Elements" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock BLOCK_ELEMENTS = new UnicodeBlock("BLOCK_ELEMENTS", 0x2580, 0x259f);
- /**
- * The "Geometric Shapes" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock GEOMETRIC_SHAPES = new UnicodeBlock("GEOMETRIC_SHAPES", 0x25a0, 0x25ff);
- /**
- * The "Miscellaneous Symbols" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock MISCELLANEOUS_SYMBOLS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS", 0x2600, 0x26ff);
- /**
- * The "Dingbats" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock DINGBATS = new UnicodeBlock("DINGBATS", 0x2700, 0x27bf);
- /**
- * The "Miscellaneous Mathematical Symbols-A" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_A", 0x27c0, 0x27ef);
- /**
- * The "Supplemental Arrows-A" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SUPPLEMENTAL_ARROWS_A = new UnicodeBlock("SUPPLEMENTAL_ARROWS_A", 0x27f0, 0x27ff);
- /**
- * The "Braille Patterns" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock BRAILLE_PATTERNS = new UnicodeBlock("BRAILLE_PATTERNS", 0x2800, 0x28ff);
- /**
- * The "Supplemental Arrows-B" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SUPPLEMENTAL_ARROWS_B = new UnicodeBlock("SUPPLEMENTAL_ARROWS_B", 0x2900, 0x297f);
- /**
- * The "Miscellaneous Mathematical Symbols-B" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B = new UnicodeBlock("MISCELLANEOUS_MATHEMATICAL_SYMBOLS_B", 0x2980, 0x29ff);
- /**
- * The "Supplemental Mathematical Operators" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SUPPLEMENTAL_MATHEMATICAL_OPERATORS = new UnicodeBlock("SUPPLEMENTAL_MATHEMATICAL_OPERATORS", 0x2a00, 0x2aff);
- /**
- * The "Miscellaneous Symbols and Arrows" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_ARROWS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_ARROWS", 0x2b00, 0x2bff);
- /**
- * The "CJK Radicals Supplement" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock CJK_RADICALS_SUPPLEMENT = new UnicodeBlock("CJK_RADICALS_SUPPLEMENT", 0x2e80, 0x2eff);
- /**
- * The "Kangxi Radicals" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock KANGXI_RADICALS = new UnicodeBlock("KANGXI_RADICALS", 0x2f00, 0x2fdf);
- /**
- * The "Ideographic Description Characters" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock IDEOGRAPHIC_DESCRIPTION_CHARACTERS = new UnicodeBlock("IDEOGRAPHIC_DESCRIPTION_CHARACTERS", 0x2ff0, 0x2fff);
- /**
- * The "CJK Symbols and Punctuation" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CJK_SYMBOLS_AND_PUNCTUATION = new UnicodeBlock("CJK_SYMBOLS_AND_PUNCTUATION", 0x3000, 0x303f);
- /**
- * The "Hiragana" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HIRAGANA = new UnicodeBlock("HIRAGANA", 0x3040, 0x309f);
- /**
- * The "Katakana" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock KATAKANA = new UnicodeBlock("KATAKANA", 0x30a0, 0x30ff);
- /**
- * The "Bopomofo" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock BOPOMOFO = new UnicodeBlock("BOPOMOFO", 0x3100, 0x312f);
- /**
- * The "Hangul Compatibility Jamo" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HANGUL_COMPATIBILITY_JAMO = new UnicodeBlock("HANGUL_COMPATIBILITY_JAMO", 0x3130, 0x318f);
- /**
- * The "Kanbun" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock KANBUN = new UnicodeBlock("KANBUN", 0x3190, 0x319f);
- /**
- * The "Bopomofo Extended" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock BOPOMOFO_EXTENDED = new UnicodeBlock("BOPOMOFO_EXTENDED", 0x31a0, 0x31bf);
- /**
- * The "Katakana Phonetic Extensions" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock KATAKANA_PHONETIC_EXTENSIONS = new UnicodeBlock("KATAKANA_PHONETIC_EXTENSIONS", 0x31f0, 0x31ff);
- /**
- * The "Enclosed CJK Letters and Months" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ENCLOSED_CJK_LETTERS_AND_MONTHS = new UnicodeBlock("ENCLOSED_CJK_LETTERS_AND_MONTHS", 0x3200, 0x32ff);
- /**
- * The "CJK Compatibility" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CJK_COMPATIBILITY = new UnicodeBlock("CJK_COMPATIBILITY", 0x3300, 0x33ff);
- /**
- * The "CJK Unified Ideographs Extension A" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A", 0x3400, 0x4dbf);
- /**
- * The "Yijing Hexagram Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock YIJING_HEXAGRAM_SYMBOLS = new UnicodeBlock("YIJING_HEXAGRAM_SYMBOLS", 0x4dc0, 0x4dff);
- /**
- * The "CJK Unified Ideographs" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS", 0x4e00, 0x9fff);
- /**
- * The "Yi Syllables" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock YI_SYLLABLES = new UnicodeBlock("YI_SYLLABLES", 0xa000, 0xa48f);
- /**
- * The "Yi Radicals" Unicode Block.
- *
- * @since 1.4
- */
- public static final UnicodeBlock YI_RADICALS = new UnicodeBlock("YI_RADICALS", 0xa490, 0xa4cf);
- /**
- * The "Hangul Syllables" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HANGUL_SYLLABLES = new UnicodeBlock("HANGUL_SYLLABLES", 0xac00, 0xd7af);
- /**
- * The "High Surrogates" Unicode Block. This block represents
+ * The High Surrogates Unicode block. This block represents
* code point values in the high surrogate range 0xD800 to 0xDB7F
*/
- public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES", 0xd800, 0xdb7f);
+ public static final UnicodeBlock HIGH_SURROGATES = new UnicodeBlock("HIGH_SURROGATES");
+
/**
- * The "High Private Use Surrogates" Unicode Block. This block
+ * The High Private Use Surrogates Unicode block. This block
* represents code point values in the high surrogate range 0xDB80 to
* 0xDBFF
*/
- public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES", 0xdb80, 0xdbff);
+ public static final UnicodeBlock HIGH_PRIVATE_USE_SURROGATES = new UnicodeBlock("HIGH_PRIVATE_USE_SURROGATES");
+
/**
- * The "Low Surrogates" Unicode Block. This block represents
+ * The Low Surrogates Unicode block. This block represents
* code point values in the low surrogate range 0xDC00 to 0xDFFF
*/
- public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES", 0xdc00, 0xdfff);
- /**
- * The "Private Use Area" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA", 0xe000, 0xf8ff);
- /**
- * The "CJK Compatibility Ideographs" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS", 0xf900, 0xfaff);
- /**
- * The "Alphabetic Presentation Forms" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS", 0xfb00, 0xfb4f);
- /**
- * The "Arabic Presentation Forms-A" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A", 0xfb50, 0xfdff);
- /**
- * The "Variation Selectors" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS", 0xfe00, 0xfe0f);
- /**
- * The "Combining Half Marks" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS", 0xfe20, 0xfe2f);
- /**
- * The "CJK Compatibility Forms" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS", 0xfe30, 0xfe4f);
- /**
- * The "Small Form Variants" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS", 0xfe50, 0xfe6f);
- /**
- * The "Arabic Presentation Forms-B" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B", 0xfe70, 0xfeff);
- /**
- * The "Halfwidth and Fullwidth Forms" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS", 0xff00, 0xffef);
- /**
- * The "Specials" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS", 0xfff0, 0xffff);
- /**
- * The "Linear B Syllabary" Unicode Block.
- *
- * @since 1.2
- */
- public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY", 0x10000, 0x1007f);
- /**
- * The "Linear B Ideograms" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS", 0x10080, 0x100ff);
- /**
- * The "Aegean Numbers" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS", 0x10100, 0x1013f);
- /**
- * The "Old Italic" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC", 0x10300, 0x1032f);
- /**
- * The "Gothic" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC", 0x10330, 0x1034f);
- /**
- * The "Ugaritic" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC", 0x10380, 0x1039f);
- /**
- * The "Deseret" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET", 0x10400, 0x1044f);
- /**
- * The "Shavian" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN", 0x10450, 0x1047f);
- /**
- * The "Osmanya" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA", 0x10480, 0x104af);
- /**
- * The "Cypriot Syllabary" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY", 0x10800, 0x1083f);
- /**
- * The "Byzantine Musical Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS", 0x1d000, 0x1d0ff);
- /**
- * The "Musical Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS", 0x1d100, 0x1d1ff);
- /**
- * The "Tai Xuan Jing Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS", 0x1d300, 0x1d35f);
- /**
- * The "Mathematical Alphanumeric Symbols" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS", 0x1d400, 0x1d7ff);
- /**
- * The "CJK Unified Ideographs Extension B" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B", 0x20000, 0x2a6df);
- /**
- * The "CJK Compatibility Ideographs Supplement" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT", 0x2f800, 0x2fa1f);
- /**
- * The "Tags" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS", 0xe0000, 0xe007f);
- /**
- * The "Variation Selectors Supplement" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT", 0xe0100, 0xe01ef);
- /**
- * The "Supplementary Private Use Area-A" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A", 0xf0000, 0xfffff);
- /**
- * The "Supplementary Private Use Area-B" Unicode Block.
- *
- * @since 1.5
- */
- public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B", 0x100000, 0x10ffff);
+ public static final UnicodeBlock LOW_SURROGATES = new UnicodeBlock("LOW_SURROGATES");
+
+ /** The Private Use Area Unicode block. */
+ public static final UnicodeBlock PRIVATE_USE_AREA = new UnicodeBlock("PRIVATE_USE_AREA");
+
+ /** The CJK Compatibility Ideographs Unicode block. */
+ public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS");
+
+ /** The Alphabetic Presentation Forms Unicode block. */
+ public static final UnicodeBlock ALPHABETIC_PRESENTATION_FORMS = new UnicodeBlock("ALPHABETIC_PRESENTATION_FORMS");
+
+ /** The Arabic Presentation Forms-A Unicode block. */
+ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_A = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_A");
+
+ /** The Variation Selectors Unicode block. */
+ public static final UnicodeBlock VARIATION_SELECTORS = new UnicodeBlock("VARIATION_SELECTORS");
+
+ /** The Combining Half Marks Unicode block. */
+ public static final UnicodeBlock COMBINING_HALF_MARKS = new UnicodeBlock("COMBINING_HALF_MARKS");
+
+ /** The CJK Compatibility Forms Unicode block. */
+ public static final UnicodeBlock CJK_COMPATIBILITY_FORMS = new UnicodeBlock("CJK_COMPATIBILITY_FORMS");
+
+ /** The Small Form Variants Unicode block. */
+ public static final UnicodeBlock SMALL_FORM_VARIANTS = new UnicodeBlock("SMALL_FORM_VARIANTS");
+
+ /** The Arabic Presentation Forms-B Unicode block. */
+ public static final UnicodeBlock ARABIC_PRESENTATION_FORMS_B = new UnicodeBlock("ARABIC_PRESENTATION_FORMS_B");
+
+ /** The Halfwidth and Fullwidth Forms Unicode block. */
+ public static final UnicodeBlock HALFWIDTH_AND_FULLWIDTH_FORMS = new UnicodeBlock("HALFWIDTH_AND_FULLWIDTH_FORMS");
+
+ /** The Specials Unicode block. */
+ public static final UnicodeBlock SPECIALS = new UnicodeBlock("SPECIALS");
+
+ /** The Linear B Syllabary Unicode block. */
+ public static final UnicodeBlock LINEAR_B_SYLLABARY = new UnicodeBlock("LINEAR_B_SYLLABARY");
+
+ /** The Linear B Ideograms Unicode block. */
+ public static final UnicodeBlock LINEAR_B_IDEOGRAMS = new UnicodeBlock("LINEAR_B_IDEOGRAMS");
+
+ /** The Aegean Numbers Unicode block. */
+ public static final UnicodeBlock AEGEAN_NUMBERS = new UnicodeBlock("AEGEAN_NUMBERS");
+
+ /** The Old Italic Unicode block. */
+ public static final UnicodeBlock OLD_ITALIC = new UnicodeBlock("OLD_ITALIC");
+
+ /** The Gothic Unicode block. */
+ public static final UnicodeBlock GOTHIC = new UnicodeBlock("GOTHIC");
+
+ /** The Ugaritic Unicode block. */
+ public static final UnicodeBlock UGARITIC = new UnicodeBlock("UGARITIC");
+
+ /** The Deseret Unicode block. */
+ public static final UnicodeBlock DESERET = new UnicodeBlock("DESERET");
+
+ /** The Shavian Unicode block. */
+ public static final UnicodeBlock SHAVIAN = new UnicodeBlock("SHAVIAN");
+
+ /** The Osmanya Unicode block. */
+ public static final UnicodeBlock OSMANYA = new UnicodeBlock("OSMANYA");
+
+ /** The Cypriot Syllabary Unicode block. */
+ public static final UnicodeBlock CYPRIOT_SYLLABARY = new UnicodeBlock("CYPRIOT_SYLLABARY");
+
+ /** The Byzantine Musical Symbols Unicode block. */
+ public static final UnicodeBlock BYZANTINE_MUSICAL_SYMBOLS = new UnicodeBlock("BYZANTINE_MUSICAL_SYMBOLS");
+
+ /** The Musical Symbols Unicode block. */
+ public static final UnicodeBlock MUSICAL_SYMBOLS = new UnicodeBlock("MUSICAL_SYMBOLS");
+
+ /** The Tai Xuan Jing Symbols Unicode block. */
+ public static final UnicodeBlock TAI_XUAN_JING_SYMBOLS = new UnicodeBlock("TAI_XUAN_JING_SYMBOLS");
+
+ /** The Mathematical Alphanumeric Symbols Unicode block. */
+ public static final UnicodeBlock MATHEMATICAL_ALPHANUMERIC_SYMBOLS = new UnicodeBlock("MATHEMATICAL_ALPHANUMERIC_SYMBOLS");
+
+ /** The CJK Unified Ideographs Extension B Unicode block. */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B");
+
+ /** The CJK Compatibility Ideographs Supplement Unicode block. */
+ public static final UnicodeBlock CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT = new UnicodeBlock("CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT");
+
+ /** The Tags Unicode block. */
+ public static final UnicodeBlock TAGS = new UnicodeBlock("TAGS");
+
+ /** The Variation Selectors Supplement Unicode block. */
+ public static final UnicodeBlock VARIATION_SELECTORS_SUPPLEMENT = new UnicodeBlock("VARIATION_SELECTORS_SUPPLEMENT");
+
+ /** The Supplementary Private Use Area-A Unicode block. */
+ public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_A = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_A");
+
+ /** The Supplementary Private Use Area-B Unicode block. */
+ public static final UnicodeBlock SUPPLEMENTARY_PRIVATE_USE_AREA_B = new UnicodeBlock("SUPPLEMENTARY_PRIVATE_USE_AREA_B");
+
+ // Unicode 4.1.
+
+ /** The Ancient Greek Musical Notation Unicode 4.1 block. */
+ public static final UnicodeBlock ANCIENT_GREEK_MUSICAL_NOTATION = new UnicodeBlock("ANCIENT_GREEK_MUSICAL_NOTATION");
+
+ /** The Ancient Greek Numbers Unicode 4.1 block. */
+ public static final UnicodeBlock ANCIENT_GREEK_NUMBERS = new UnicodeBlock("ANCIENT_GREEK_NUMBERS");
+
+ /** The Arabic Supplement Unicode 4.1 block. */
+ public static final UnicodeBlock ARABIC_SUPPLEMENT = new UnicodeBlock("ARABIC_SUPPLEMENT");
+
+ /** The Buginese Unicode 4.1 block. */
+ public static final UnicodeBlock BUGINESE = new UnicodeBlock("BUGINESE");
+
+ /** The CJK Strokes Unicode 4.1 block. */
+ public static final UnicodeBlock CJK_STROKES = new UnicodeBlock("CJK_STROKES");
+
+ /** The Combining Diacritical Marks Supplement Unicode 4.1 block. */
+ public static final UnicodeBlock COMBINING_DIACRITICAL_MARKS_SUPPLEMENT = new UnicodeBlock("COMBINING_DIACRITICAL_MARKS_SUPPLEMENT");
+
+ /** The Coptic Unicode 4.1 block. */
+ public static final UnicodeBlock COPTIC = new UnicodeBlock("COPTIC");
+
+ /** The Ethiopic Extended Unicode 4.1 block. */
+ public static final UnicodeBlock ETHIOPIC_EXTENDED = new UnicodeBlock("ETHIOPIC_EXTENDED");
+
+ /** The Ethiopic Supplement Unicode 4.1 block. */
+ public static final UnicodeBlock ETHIOPIC_SUPPLEMENT = new UnicodeBlock("ETHIOPIC_SUPPLEMENT");
+
+ /** The Georgian Supplement Unicode 4.1 block. */
+ public static final UnicodeBlock GEORGIAN_SUPPLEMENT = new UnicodeBlock("GEORGIAN_SUPPLEMENT");
+
+ /** The Glagolitic Unicode 4.1 block. */
+ public static final UnicodeBlock GLAGOLITIC = new UnicodeBlock("GLAGOLITIC");
+
+ /** The Kharoshthi Unicode 4.1 block. */
+ public static final UnicodeBlock KHAROSHTHI = new UnicodeBlock("KHAROSHTHI");
+
+ /** The Modifier Tone Letters Unicode 4.1 block. */
+ public static final UnicodeBlock MODIFIER_TONE_LETTERS = new UnicodeBlock("MODIFIER_TONE_LETTERS");
+
+ /** The New Tai Lue Unicode 4.1 block. */
+ public static final UnicodeBlock NEW_TAI_LUE = new UnicodeBlock("NEW_TAI_LUE");
+
+ /** The Old Persian Unicode 4.1 block. */
+ public static final UnicodeBlock OLD_PERSIAN = new UnicodeBlock("OLD_PERSIAN");
+
+ /** The Phonetic Extensions Supplement Unicode 4.1 block. */
+ public static final UnicodeBlock PHONETIC_EXTENSIONS_SUPPLEMENT = new UnicodeBlock("PHONETIC_EXTENSIONS_SUPPLEMENT");
+
+ /** The Supplemental Punctuation Unicode 4.1 block. */
+ public static final UnicodeBlock SUPPLEMENTAL_PUNCTUATION = new UnicodeBlock("SUPPLEMENTAL_PUNCTUATION");
+
+ /** The Syloti Nagri Unicode 4.1 block. */
+ public static final UnicodeBlock SYLOTI_NAGRI = new UnicodeBlock("SYLOTI_NAGRI");
+
+ /** The Tifinagh Unicode 4.1 block. */
+ public static final UnicodeBlock TIFINAGH = new UnicodeBlock("TIFINAGH");
+
+ /** The Vertical Forms Unicode 4.1 block. */
+ public static final UnicodeBlock VERTICAL_FORMS = new UnicodeBlock("VERTICAL_FORMS");
+
+ // Unicode 5.0.
+
+ /** The NKo Unicode 5.0 block. */
+ public static final UnicodeBlock NKO = new UnicodeBlock("NKO");
+
+ /** The Balinese Unicode 5.0 block. */
+ public static final UnicodeBlock BALINESE = new UnicodeBlock("BALINESE");
+
+ /** The Latin Extended C Unicode 5.0 block. */
+ public static final UnicodeBlock LATIN_EXTENDED_C = new UnicodeBlock("LATIN_EXTENDED_C");
+
+ /** The Latin Extended D Unicode 5.0 block. */
+ public static final UnicodeBlock LATIN_EXTENDED_D = new UnicodeBlock("LATIN_EXTENDED_D");
+
+ /** The Phags-pa Unicode 5.0 block. */
+ public static final UnicodeBlock PHAGS_PA = new UnicodeBlock("PHAGS_PA");
+
+ /** The Phoenician Unicode 5.0 block. */
+ public static final UnicodeBlock PHOENICIAN = new UnicodeBlock("PHOENICIAN");
+
+ /** The Cuneiform Unicode 5.0 block. */
+ public static final UnicodeBlock CUNEIFORM = new UnicodeBlock("CUNEIFORM");
+
+ /** The Cuneiform Numbers And Punctuation Unicode 5.0 block. */
+ public static final UnicodeBlock CUNEIFORM_NUMBERS_AND_PUNCTUATION = new UnicodeBlock("CUNEIFORM_NUMBERS_AND_PUNCTUATION");
+
+ /** The Counting Rod Numerals Unicode 5.0 block. */
+ public static final UnicodeBlock COUNTING_ROD_NUMERALS = new UnicodeBlock("COUNTING_ROD_NUMERALS");
+
+ // Unicode 5.1.
+
+ /** The Sudanese Unicode 5.1 block. */
+ public static final UnicodeBlock SUNDANESE = new UnicodeBlock("SUNDANESE");
+
+ /** The Lepcha Unicode 5.1 block. */
+ public static final UnicodeBlock LEPCHA = new UnicodeBlock("LEPCHA");
+
+ /** The Ol Chiki Unicode 5.1 block. */
+ public static final UnicodeBlock OL_CHIKI = new UnicodeBlock("OL_CHIKI");
+
+ /** The Cyrillic Extended-A Unicode 5.1 block. */
+ public static final UnicodeBlock CYRILLIC_EXTENDED_A = new UnicodeBlock("CYRILLIC_EXTENDED_A");
+
+ /** The Vai Unicode 5.1 block. */
+ public static final UnicodeBlock VAI = new UnicodeBlock("VAI");
+
+ /** The Cyrillic Extended-B Unicode 5.1 block. */
+ public static final UnicodeBlock CYRILLIC_EXTENDED_B = new UnicodeBlock("CYRILLIC_EXTENDED_B");
+
+ /** The Saurashtra Unicode 5.1 block. */
+ public static final UnicodeBlock SAURASHTRA = new UnicodeBlock("SAURASHTRA");
+
+ /** The Kayah Li Unicode 5.1 block. */
+ public static final UnicodeBlock KAYAH_LI = new UnicodeBlock("KAYAH_LI");
+
+ /** The Rejang Unicode 5.1 block. */
+ public static final UnicodeBlock REJANG = new UnicodeBlock("REJANG");
+
+ /** The Cham Unicode 5.1 block. */
+ public static final UnicodeBlock CHAM = new UnicodeBlock("CHAM");
+
+ /** The Ancient Symbols Unicode 5.1 block. */
+ public static final UnicodeBlock ANCIENT_SYMBOLS = new UnicodeBlock("ANCIENT_SYMBOLS");
+
+ /** The Phaistos Disc Unicode 5.1 block. */
+ public static final UnicodeBlock PHAISTOS_DISC = new UnicodeBlock("PHAISTOS_DISC");
+
+ /** The Lycian Unicode 5.1 block. */
+ public static final UnicodeBlock LYCIAN = new UnicodeBlock("LYCIAN");
+
+ /** The Carian Unicode 5.1 block. */
+ public static final UnicodeBlock CARIAN = new UnicodeBlock("CARIAN");
+
+ /** The Lydian Unicode 5.1 block. */
+ public static final UnicodeBlock LYDIAN = new UnicodeBlock("LYDIAN");
+
+ /** The Mahjong Tiles Unicode 5.1 block. */
+ public static final UnicodeBlock MAHJONG_TILES = new UnicodeBlock("MAHJONG_TILES");
+
+ /** The Domino Tiles Unicode 5.1 block. */
+ public static final UnicodeBlock DOMINO_TILES = new UnicodeBlock("DOMINO_TILES");
+
+ // Unicode 5.2.
+
+ /** The Samaritan Unicode 5.2 block. */
+ public static final UnicodeBlock SAMARITAN = new UnicodeBlock("SAMARITAN");
+
+ /** The Unified Canadian Aboriginal Syllabics Expanded Unicode 5.2 block. */
+ public static final UnicodeBlock UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED = new UnicodeBlock("UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED");
+
+ /** The Tai Tham Unicode 5.2 block. */
+ public static final UnicodeBlock TAI_THAM = new UnicodeBlock("TAI_THAM");
+
+ /** The Vedic Extensions Unicode 5.2 block. */
+ public static final UnicodeBlock VEDIC_EXTENSIONS = new UnicodeBlock("VEDIC_EXTENSIONS");
+
+ /** The Lisu Extensions Unicode 5.2 block. */
+ public static final UnicodeBlock LISU = new UnicodeBlock("LISU");
+
+ /** The Bamum Extensions Unicode 5.2 block. */
+ public static final UnicodeBlock BAMUM = new UnicodeBlock("BAMUM");
+
+ /** The Common Indic Number Forms Unicode 5.2 block. */
+ public static final UnicodeBlock COMMON_INDIC_NUMBER_FORMS = new UnicodeBlock("COMMON_INDIC_NUMBER_FORMS");
+
+ /** The Devanagari Extended Unicode 5.2 block. */
+ public static final UnicodeBlock DEVANAGARI_EXTENDED = new UnicodeBlock("DEVANAGARI_EXTENDED");
+
+ /** The Hangul Jamo Extended-A Unicode 5.2 block. */
+ public static final UnicodeBlock HANGUL_JAMO_EXTENDED_A = new UnicodeBlock("HANGUL_JAMO_EXTENDED_A");
+
+ /** The Javanese Unicode 5.2 block. */
+ public static final UnicodeBlock JAVANESE = new UnicodeBlock("JAVANESE");
+
+ /** The Myanmar Extended-A Unicode 5.2 block. */
+ public static final UnicodeBlock MYANMAR_EXTENDED_A = new UnicodeBlock("MYANMAR_EXTENDED_A");
+
+ /** The Tai Viet Unicode 5.2 block. */
+ public static final UnicodeBlock TAI_VIET = new UnicodeBlock("TAI_VIET");
+
+ /** The Meetei Mayek Unicode 5.2 block. */
+ public static final UnicodeBlock MEETEI_MAYEK = new UnicodeBlock("MEETEI_MAYEK");
+
+ /** The Hangul Jamo Extended-B Unicode 5.2 block. */
+ public static final UnicodeBlock HANGUL_JAMO_EXTENDED_B = new UnicodeBlock("HANGUL_JAMO_EXTENDED_B");
+
+ /** The Imperial Aramaic Unicode 5.2 block. */
+ public static final UnicodeBlock IMPERIAL_ARAMAIC = new UnicodeBlock("IMPERIAL_ARAMAIC");
+
+ /** The Old South Arabian Unicode 5.2 block. */
+ public static final UnicodeBlock OLD_SOUTH_ARABIAN = new UnicodeBlock("OLD_SOUTH_ARABIAN");
+
+ /** The Avestan Unicode 5.2 block. */
+ public static final UnicodeBlock AVESTAN = new UnicodeBlock("AVESTAN");
+
+ /** The Inscriptional Pathian Unicode 5.2 block. */
+ public static final UnicodeBlock INSCRIPTIONAL_PARTHIAN = new UnicodeBlock("INSCRIPTIONAL_PARTHIAN");
+
+ /** The Inscriptional Pahlavi Unicode 5.2 block. */
+ public static final UnicodeBlock INSCRIPTIONAL_PAHLAVI = new UnicodeBlock("INSCRIPTIONAL_PAHLAVI");
+
+ /** The Old Turkic Unicode 5.2 block. */
+ public static final UnicodeBlock OLD_TURKIC = new UnicodeBlock("OLD_TURKIC");
+
+ /** The Rumi Numeral Symbols Unicode 5.2 block. */
+ public static final UnicodeBlock RUMI_NUMERAL_SYMBOLS = new UnicodeBlock("RUMI_NUMERAL_SYMBOLS");
+
+ /** The Kaithi Unicode 5.2 block. */
+ public static final UnicodeBlock KAITHI = new UnicodeBlock("KAITHI");
+
+ /** The Egyptian Hieroglyphs Unicode 5.2 block. */
+ public static final UnicodeBlock EGYPTIAN_HIEROGLYPHS = new UnicodeBlock("EGYPTIAN_HIEROGLYPHS");
+
+ /** The Enclosed Alphanumeric Supplement Unicode 5.2 block. */
+ public static final UnicodeBlock ENCLOSED_ALPHANUMERIC_SUPPLEMENT = new UnicodeBlock("ENCLOSED_ALPHANUMERIC_SUPPLEMENT");
+
+ /** The Enclosed Ideographic Supplement Unicode 5.2 block. */
+ public static final UnicodeBlock ENCLOSED_IDEOGRAPHIC_SUPPLEMENT = new UnicodeBlock("ENCLOSED_IDEOGRAPHIC_SUPPLEMENT");
+
+ /** The CJK Unified Ideographs Unicode 5.2 block. */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C");
+
+ // Unicode 6.0.
+
+ /** The Mandaic Unicode 6.0 block. */
+ public static final UnicodeBlock MANDAIC = new UnicodeBlock("MANDAIC");
+
+ /** The Batak Unicode 6.0 block. */
+ public static final UnicodeBlock BATAK = new UnicodeBlock("BATAK");
+
+ /** The Ethiopic Extended-A Unicode 6.0 block. */
+ public static final UnicodeBlock ETHIOPIC_EXTENDED_A = new UnicodeBlock("ETHIOPIC_EXTENDED_A");
+
+ /** The Brahmi Unicode 6.0 block. */
+ public static final UnicodeBlock BRAHMI = new UnicodeBlock("BRAHMI");
+
+ /** The Bamum Supplement Unicode 6.0 block. */
+ public static final UnicodeBlock BAMUM_SUPPLEMENT = new UnicodeBlock("BAMUM_SUPPLEMENT");
+
+ /** The Kana Supplement Unicode 6.0 block. */
+ public static final UnicodeBlock KANA_SUPPLEMENT = new UnicodeBlock("KANA_SUPPLEMENT");
+
+ /** The Playing Cards Supplement Unicode 6.0 block. */
+ public static final UnicodeBlock PLAYING_CARDS = new UnicodeBlock("PLAYING_CARDS");
+
+ /** The Miscellaneous Symbols And Pictographs Supplement Unicode 6.0 block. */
+ public static final UnicodeBlock MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS = new UnicodeBlock("MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS");
+
+ /** The Emoticons Unicode 6.0 block. */
+ public static final UnicodeBlock EMOTICONS = new UnicodeBlock("EMOTICONS");
+
+ /** The Transport And Map Symbols Unicode 6.0 block. */
+ public static final UnicodeBlock TRANSPORT_AND_MAP_SYMBOLS = new UnicodeBlock("TRANSPORT_AND_MAP_SYMBOLS");
+
+ /** The Alchemical Symbols Unicode 6.0 block. */
+ public static final UnicodeBlock ALCHEMICAL_SYMBOLS = new UnicodeBlock("ALCHEMICAL_SYMBOLS");
+
+ /** The CJK Unified Ideographs Extension-D Unicode 6.0 block. */
+ public static final UnicodeBlock CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D = new UnicodeBlock("CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D");
/*
- * All of the UnicodeBlocks with valid ranges in ascending order.
+ * All of the UnicodeBlocks above, in the icu4c UBlock enum order.
*/
private static UnicodeBlock[] BLOCKS = new UnicodeBlock[] {
- null,
+ null, // icu4c numbers blocks starting at 1, so index 0 should be null.
+
UnicodeBlock.BASIC_LATIN,
UnicodeBlock.LATIN_1_SUPPLEMENT,
UnicodeBlock.LATIN_EXTENDED_A,
@@ -1435,6 +1324,8 @@
UnicodeBlock.ARABIC_PRESENTATION_FORMS_B,
UnicodeBlock.SPECIALS,
UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS,
+
+ // Unicode 3.1.
UnicodeBlock.OLD_ITALIC,
UnicodeBlock.GOTHIC,
UnicodeBlock.DESERET,
@@ -1444,6 +1335,8 @@
UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B,
UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT,
UnicodeBlock.TAGS,
+
+ // Unicode 3.2.
UnicodeBlock.CYRILLIC_SUPPLEMENTARY,
UnicodeBlock.TAGALOG,
UnicodeBlock.HANUNOO,
@@ -1458,6 +1351,8 @@
UnicodeBlock.VARIATION_SELECTORS,
UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_A,
UnicodeBlock.SUPPLEMENTARY_PRIVATE_USE_AREA_B,
+
+ // Unicode 4.0.
UnicodeBlock.LIMBU,
UnicodeBlock.TAI_LE,
UnicodeBlock.KHMER_SYMBOLS,
@@ -1472,32 +1367,122 @@
UnicodeBlock.OSMANYA,
UnicodeBlock.CYPRIOT_SYLLABARY,
UnicodeBlock.TAI_XUAN_JING_SYMBOLS,
- UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT
+ UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT,
+
+ // Unicode 4.1.
+ UnicodeBlock.ANCIENT_GREEK_MUSICAL_NOTATION,
+ UnicodeBlock.ANCIENT_GREEK_NUMBERS,
+ UnicodeBlock.ARABIC_SUPPLEMENT,
+ UnicodeBlock.BUGINESE,
+ UnicodeBlock.CJK_STROKES,
+ UnicodeBlock.COMBINING_DIACRITICAL_MARKS_SUPPLEMENT,
+ UnicodeBlock.COPTIC,
+ UnicodeBlock.ETHIOPIC_EXTENDED,
+ UnicodeBlock.ETHIOPIC_SUPPLEMENT,
+ UnicodeBlock.GEORGIAN_SUPPLEMENT,
+ UnicodeBlock.GLAGOLITIC,
+ UnicodeBlock.KHAROSHTHI,
+ UnicodeBlock.MODIFIER_TONE_LETTERS,
+ UnicodeBlock.NEW_TAI_LUE,
+ UnicodeBlock.OLD_PERSIAN,
+ UnicodeBlock.PHONETIC_EXTENSIONS_SUPPLEMENT,
+ UnicodeBlock.SUPPLEMENTAL_PUNCTUATION,
+ UnicodeBlock.SYLOTI_NAGRI,
+ UnicodeBlock.TIFINAGH,
+ UnicodeBlock.VERTICAL_FORMS,
+
+ // Unicode 5.0.
+ UnicodeBlock.NKO,
+ UnicodeBlock.BALINESE,
+ UnicodeBlock.LATIN_EXTENDED_C,
+ UnicodeBlock.LATIN_EXTENDED_D,
+ UnicodeBlock.PHAGS_PA,
+ UnicodeBlock.PHOENICIAN,
+ UnicodeBlock.CUNEIFORM,
+ UnicodeBlock.CUNEIFORM_NUMBERS_AND_PUNCTUATION,
+ UnicodeBlock.COUNTING_ROD_NUMERALS,
+
+ // Unicode 5.1.
+ UnicodeBlock.SUNDANESE,
+ UnicodeBlock.LEPCHA,
+ UnicodeBlock.OL_CHIKI,
+ UnicodeBlock.CYRILLIC_EXTENDED_A,
+ UnicodeBlock.VAI,
+ UnicodeBlock.CYRILLIC_EXTENDED_B,
+ UnicodeBlock.SAURASHTRA,
+ UnicodeBlock.KAYAH_LI,
+ UnicodeBlock.REJANG,
+ UnicodeBlock.CHAM,
+ UnicodeBlock.ANCIENT_SYMBOLS,
+ UnicodeBlock.PHAISTOS_DISC,
+ UnicodeBlock.LYCIAN,
+ UnicodeBlock.CARIAN,
+ UnicodeBlock.LYDIAN,
+ UnicodeBlock.MAHJONG_TILES,
+ UnicodeBlock.DOMINO_TILES,
+
+ // Unicode 5.2.
+ UnicodeBlock.SAMARITAN,
+ UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS_EXTENDED,
+ UnicodeBlock.TAI_THAM,
+ UnicodeBlock.VEDIC_EXTENSIONS,
+ UnicodeBlock.LISU,
+ UnicodeBlock.BAMUM,
+ UnicodeBlock.COMMON_INDIC_NUMBER_FORMS,
+ UnicodeBlock.DEVANAGARI_EXTENDED,
+ UnicodeBlock.HANGUL_JAMO_EXTENDED_A,
+ UnicodeBlock.JAVANESE,
+ UnicodeBlock.MYANMAR_EXTENDED_A,
+ UnicodeBlock.TAI_VIET,
+ UnicodeBlock.MEETEI_MAYEK,
+ UnicodeBlock.HANGUL_JAMO_EXTENDED_B,
+ UnicodeBlock.IMPERIAL_ARAMAIC,
+ UnicodeBlock.OLD_SOUTH_ARABIAN,
+ UnicodeBlock.AVESTAN,
+ UnicodeBlock.INSCRIPTIONAL_PARTHIAN,
+ UnicodeBlock.INSCRIPTIONAL_PAHLAVI,
+ UnicodeBlock.OLD_TURKIC,
+ UnicodeBlock.RUMI_NUMERAL_SYMBOLS,
+ UnicodeBlock.KAITHI,
+ UnicodeBlock.EGYPTIAN_HIEROGLYPHS,
+ UnicodeBlock.ENCLOSED_ALPHANUMERIC_SUPPLEMENT,
+ UnicodeBlock.ENCLOSED_IDEOGRAPHIC_SUPPLEMENT,
+ UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_C,
+
+ // Unicode 6.0.
+ UnicodeBlock.MANDAIC,
+ UnicodeBlock.BATAK,
+ UnicodeBlock.ETHIOPIC_EXTENDED_A,
+ UnicodeBlock.BRAHMI,
+ UnicodeBlock.BAMUM_SUPPLEMENT,
+ UnicodeBlock.KANA_SUPPLEMENT,
+ UnicodeBlock.PLAYING_CARDS,
+ UnicodeBlock.MISCELLANEOUS_SYMBOLS_AND_PICTOGRAPHS,
+ UnicodeBlock.EMOTICONS,
+ UnicodeBlock.TRANSPORT_AND_MAP_SYMBOLS,
+ UnicodeBlock.ALCHEMICAL_SYMBOLS,
+ UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_D,
};
/**
- * Retrieves the constant that corresponds to the specified block name.
- * The block names are defined by the Unicode 4.0.1 specification in the
- * {@code Blocks-4.0.1.txt} file.
- * <p>
- * Block names may be one of the following:
+ * Returns the Unicode block for the given block name, or null if there is no
+ * such block.
+ *
+ * <p>Block names may be one of the following:
* <ul>
* <li>Canonical block name, as defined by the Unicode specification;
* case-insensitive.</li>
* <li>Canonical block name without any spaces, as defined by the
* Unicode specification; case-insensitive.</li>
- * <li>{@code UnicodeBlock} constant identifier. This is determined by
- * uppercasing the canonical name and replacing all spaces and hyphens
+ * <li>A {@code UnicodeBlock} constant identifier. This is determined by
+ * converting the canonical name to uppercase and replacing all spaces and hyphens
* with underscores.</li>
* </ul>
*
- * @param blockName
- * the name of the block to retrieve.
- * @return the UnicodeBlock constant corresponding to {@code blockName}.
* @throws NullPointerException
- * if {@code blockName} is {@code null}.
+ * if {@code blockName == null}.
* @throws IllegalArgumentException
- * if {@code blockName} is not a valid block name.
+ * if {@code blockName} is not the name of any known block.
* @since 1.5
*/
public static UnicodeBlock forName(String blockName) {
@@ -1506,47 +1491,22 @@
}
int block = forNameImpl(blockName);
if (block == -1) {
- if (blockName.equals("SURROGATES_AREA")) {
- return SURROGATES_AREA;
- } else if(blockName.equalsIgnoreCase("greek")) {
- return GREEK;
- } else if(blockName.equals("COMBINING_MARKS_FOR_SYMBOLS") ||
- blockName.equals("Combining Marks for Symbols") ||
- blockName.equals("CombiningMarksforSymbols")) {
- return COMBINING_MARKS_FOR_SYMBOLS;
- }
- throw new IllegalArgumentException("Bad block name: " + blockName);
+ throw new IllegalArgumentException("Unknown block: " + blockName);
}
return BLOCKS[block];
}
/**
- * Gets the constant for the Unicode block that contains the specified
- * character.
- *
- * @param c
- * the character for which to get the {@code UnicodeBlock}
- * constant.
- * @return the {@code UnicodeBlock} constant for the block that contains
- * {@code c}, or {@code null} if {@code c} does not belong to
- * any defined block.
+ * Returns the Unicode block containing the given code point, or null if the
+ * code point does not belong to any known block.
*/
public static UnicodeBlock of(char c) {
return of((int) c);
}
/**
- * Gets the constant for the Unicode block that contains the specified
- * Unicode code point.
- *
- * @param codePoint
- * the Unicode code point for which to get the
- * {@code UnicodeBlock} constant.
- * @return the {@code UnicodeBlock} constant for the block that contains
- * {@code codePoint}, or {@code null} if {@code codePoint} does
- * not belong to any defined block.
- * @throws IllegalArgumentException if {@code codePoint} is not a valid code point.
- * @since 1.5
+ * Returns the Unicode block containing the given code point, or null if the
+ * code point does not belong to any known block.
*/
public static UnicodeBlock of(int codePoint) {
checkValidCodePoint(codePoint);
@@ -1557,7 +1517,7 @@
return BLOCKS[block];
}
- private UnicodeBlock(String blockName, int start, int end) {
+ private UnicodeBlock(String blockName) {
super(blockName);
}
}
@@ -1614,7 +1574,6 @@
* Compares two {@code char} values.
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* @since 1.7
- * @hide 1.7
*/
public static int compare(char lhs, char rhs) {
return lhs - rhs;
@@ -1706,9 +1665,8 @@
}
/**
- * Tests whether the given character is a high or low surrogate.
+ * Returns true if the given character is a high or low surrogate.
* @since 1.7
- * @hide 1.7
*/
public static boolean isSurrogate(char ch) {
return ch >= MIN_SURROGATE && ch <= MAX_SURROGATE;
@@ -2433,7 +2391,8 @@
}
/**
- * Returns the name of the given code point, or null if the code point is unassigned.
+ * Returns a human-readable name for the given code point,
+ * or null if the code point is unassigned.
*
* <p>As a fallback mechanism this method returns strings consisting of the Unicode
* block name (with underscores replaced by spaces), a single space, and the uppercase
@@ -2447,9 +2406,10 @@
* <li>{@code Character.getName(0xe000)} returns "PRIVATE USE AREA E000".
* </ul>
*
+ * <p>Note that the exact strings returned will vary from release to release.
+ *
* @throws IllegalArgumentException if {@code codePoint} is not a valid code point.
* @since 1.7
- * @hide 1.7
*/
public static String getName(int codePoint) {
checkValidCodePoint(codePoint);
@@ -2620,7 +2580,6 @@
* Returns the high surrogate for the given code point. The result is meaningless if
* the given code point is not a supplementary character.
* @since 1.7
- * @hide 1.7
*/
public static char highSurrogate(int codePoint) {
return (char) ((codePoint >> 10) + 0xd7c0);
@@ -2630,20 +2589,25 @@
* Returns the low surrogate for the given code point. The result is meaningless if
* the given code point is not a supplementary character.
* @since 1.7
- * @hide 1.7
*/
public static char lowSurrogate(int codePoint) {
return (char) ((codePoint & 0x3ff) | 0xdc00);
}
/**
- * Tests whether the given code point is in the Basic Multilingual Plane (BMP).
+ * Returns true if the given code point is alphabetic. That is,
+ * if it is in any of the Lu, Ll, Lt, Lm, Lo, Nl, or Other_Alphabetic categories.
+ * @since 1.7
+ */
+ public static native boolean isAlphabetic(int codePoint);
+
+ /**
+ * Returns true if the given code point is in the Basic Multilingual Plane (BMP).
* Such code points can be represented by a single {@code char}.
* @since 1.7
- * @hide 1.7
*/
public static boolean isBmpCodePoint(int codePoint) {
- return codePoint >= 0 && codePoint <= 0xffff;
+ return codePoint >= Character.MIN_VALUE && codePoint <= Character.MAX_VALUE;
}
/**
@@ -2720,6 +2684,12 @@
}
/**
+ * Returns true if the given code point is a CJKV ideographic character.
+ * @since 1.7
+ */
+ public static native boolean isIdeographic(int codePoint);
+
+ /**
* Indicates whether the specified code point is ignorable in a Java or
* Unicode identifier.
*
@@ -2842,7 +2812,7 @@
* the character to check.
* @return {@code true} if {@code c} is a Java letter; {@code false}
* otherwise.
- * @deprecated Use {@link #isJavaIdentifierStart(char)}
+ * @deprecated Use {@link #isJavaIdentifierStart(char)} instead.
*/
@Deprecated
public static boolean isJavaLetter(char c) {
@@ -2857,7 +2827,7 @@
* the character to check.
* @return {@code true} if {@code c} is a Java letter or digit;
* {@code false} otherwise.
- * @deprecated Use {@link #isJavaIdentifierPart(char)}
+ * @deprecated Use {@link #isJavaIdentifierPart(char)} instead.
*/
@Deprecated
public static boolean isJavaLetterOrDigit(char c) {
@@ -2965,13 +2935,8 @@
private static native boolean isLowerCaseImpl(int codePoint);
/**
- * Indicates whether the specified character is a Java space.
- *
- * @param c
- * the character to check.
- * @return {@code true} if {@code c} is a Java space; {@code false}
- * otherwise.
- * @deprecated Use {@link #isWhitespace(char)}
+ * Use {@link #isWhitespace(char)} instead.
+ * @deprecated Use {@link #isWhitespace(char)} instead.
*/
@Deprecated
public static boolean isSpace(char c) {
@@ -2979,40 +2944,41 @@
}
/**
- * Indicates whether the specified character is a Unicode space character.
- * That is, if it is a member of one of the Unicode categories Space
- * Separator, Line Separator, or Paragraph Separator.
- *
- * @param c
- * the character to check.
- * @return {@code true} if {@code c} is a Unicode space character,
- * {@code false} otherwise.
+ * See {@link #isSpaceChar(int)}.
*/
public static boolean isSpaceChar(char c) {
return isSpaceChar((int) c);
}
/**
- * Indicates whether the specified code point is a Unicode space character.
- * That is, if it is a member of one of the Unicode categories Space
- * Separator, Line Separator, or Paragraph Separator.
- *
- * @param codePoint
- * the code point to check.
- * @return {@code true} if {@code codePoint} is a Unicode space character,
- * {@code false} otherwise.
+ * Returns true if the given code point is a Unicode space character.
+ * The exact set of characters considered as whitespace varies with Unicode version.
+ * Note that non-breaking spaces are considered whitespace.
+ * Note also that line separators are not considered whitespace; see {@link #isWhitespace}
+ * for an alternative.
*/
public static boolean isSpaceChar(int codePoint) {
- if (codePoint == 0x20 || codePoint == 0xa0 || codePoint == 0x1680) {
+ // We don't just call into icu4c because of the JNI overhead. Ideally we'd fix that.
+ // SPACE or NO-BREAK SPACE?
+ if (codePoint == 0x20 || codePoint == 0xa0) {
+ return true;
+ }
+ if (codePoint < 0x1000) {
+ return false;
+ }
+ // OGHAM SPACE MARK or MONGOLIAN VOWEL SEPARATOR?
+ if (codePoint == 0x1680 || codePoint == 0x180e) {
return true;
}
if (codePoint < 0x2000) {
return false;
}
if (codePoint <= 0xffff) {
- return codePoint <= 0x200b || codePoint == 0x2028 || codePoint == 0x2029 ||
- codePoint == 0x202f || codePoint == 0x3000;
+ // Other whitespace from General Punctuation...
+ return codePoint <= 0x200a || codePoint == 0x2028 || codePoint == 0x2029 || codePoint == 0x202f || codePoint == 0x205f ||
+ codePoint == 0x3000; // ...or CJK Symbols and Punctuation?
}
+ // Let icu4c worry about non-BMP code points.
return isSpaceCharImpl(codePoint);
}
@@ -3134,42 +3100,45 @@
private static native boolean isUpperCaseImpl(int codePoint);
/**
- * Indicates whether the specified character is a whitespace character in
- * Java.
- *
- * @param c
- * the character to check.
- * @return {@code true} if the supplied {@code c} is a whitespace character
- * in Java; {@code false} otherwise.
+ * See {@link #isWhitespace(int)}.
*/
public static boolean isWhitespace(char c) {
return isWhitespace((int) c);
}
/**
- * Indicates whether the specified code point is a whitespace character in
- * Java.
- *
- * @param codePoint
- * the code point to check.
- * @return {@code true} if the supplied {@code c} is a whitespace character
- * in Java; {@code false} otherwise.
+ * Returns true if the given code point is a Unicode whitespace character.
+ * The exact set of characters considered as whitespace varies with Unicode version.
+ * Note that non-breaking spaces are not considered whitespace.
+ * Note also that line separators are considered whitespace; see {@link #isSpaceChar}
+ * for an alternative.
*/
public static boolean isWhitespace(int codePoint) {
- // This is both an optimization and papers over differences between Java and ICU.
- if ((codePoint >= 0x1c && codePoint <= 0x20) || (codePoint >= 0x9 && codePoint <= 0xd)) {
+ // We don't just call into icu4c because of the JNI overhead. Ideally we'd fix that.
+ // Any ASCII whitespace character?
+ if ((codePoint >= 0x1c && codePoint <= 0x20) || (codePoint >= 0x09 && codePoint <= 0x0d)) {
return true;
}
- if (codePoint == 0x1680) {
+ if (codePoint < 0x1000) {
+ return false;
+ }
+ // OGHAM SPACE MARK or MONGOLIAN VOWEL SEPARATOR?
+ if (codePoint == 0x1680 || codePoint == 0x180e) {
return true;
}
- if (codePoint < 0x2000 || codePoint == 0x2007) {
+ if (codePoint < 0x2000) {
+ return false;
+ }
+ // Exclude General Punctuation's non-breaking spaces (which includes FIGURE SPACE).
+ if (codePoint == 0x2007 || codePoint == 0x202f) {
return false;
}
if (codePoint <= 0xffff) {
- return codePoint <= 0x200b || codePoint == 0x2028 || codePoint == 0x2029 ||
- codePoint == 0x3000;
+ // Other whitespace from General Punctuation...
+ return codePoint <= 0x200a || codePoint == 0x2028 || codePoint == 0x2029 || codePoint == 0x205f ||
+ codePoint == 0x3000; // ...or CJK Symbols and Punctuation?
}
+ // Let icu4c worry about non-BMP code points.
return isWhitespaceImpl(codePoint);
}
diff --git a/luni/src/main/java/java/lang/ClassNotFoundException.java b/luni/src/main/java/java/lang/ClassNotFoundException.java
index 2ac3b49..c7ac51d 100644
--- a/luni/src/main/java/java/lang/ClassNotFoundException.java
+++ b/luni/src/main/java/java/lang/ClassNotFoundException.java
@@ -20,7 +20,7 @@
/**
* Thrown when a class loader is unable to find a class.
*/
-public class ClassNotFoundException extends Exception {
+public class ClassNotFoundException extends ReflectiveOperationException {
private static final long serialVersionUID = 9176873029745254542L;
diff --git a/luni/src/main/java/java/lang/IllegalAccessException.java b/luni/src/main/java/java/lang/IllegalAccessException.java
index 4625395..63fae94 100644
--- a/luni/src/main/java/java/lang/IllegalAccessException.java
+++ b/luni/src/main/java/java/lang/IllegalAccessException.java
@@ -21,7 +21,7 @@
* Thrown when a program attempts to access a field or method which is not
* accessible from the location where the reference is made.
*/
-public class IllegalAccessException extends Exception {
+public class IllegalAccessException extends ReflectiveOperationException {
private static final long serialVersionUID = 6616958222490762034L;
diff --git a/luni/src/main/java/java/lang/InstantiationException.java b/luni/src/main/java/java/lang/InstantiationException.java
index a5f288b..d08cc75 100644
--- a/luni/src/main/java/java/lang/InstantiationException.java
+++ b/luni/src/main/java/java/lang/InstantiationException.java
@@ -21,7 +21,7 @@
* Thrown when a program attempts to access a constructor which is not
* accessible from the location where the reference is made.
*/
-public class InstantiationException extends Exception {
+public class InstantiationException extends ReflectiveOperationException {
private static final long serialVersionUID = -8441929162975509110L;
/**
diff --git a/luni/src/main/java/java/lang/Integer.java b/luni/src/main/java/java/lang/Integer.java
index 15511a8..fc38b41 100644
--- a/luni/src/main/java/java/lang/Integer.java
+++ b/luni/src/main/java/java/lang/Integer.java
@@ -128,7 +128,6 @@
* Compares two {@code int} values.
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* @since 1.7
- * @hide 1.7
*/
public static int compare(int lhs, int rhs) {
return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
diff --git a/luni/src/main/java/java/lang/LinkageError.java b/luni/src/main/java/java/lang/LinkageError.java
index 0bd0a53..07f58f4 100644
--- a/luni/src/main/java/java/lang/LinkageError.java
+++ b/luni/src/main/java/java/lang/LinkageError.java
@@ -49,7 +49,6 @@
/**
* Constructs a new {@code LinkageError} with the given detail message and cause.
* @since 1.7
- * @hide 1.7
*/
public LinkageError(String detailMessage, Throwable cause) {
super(detailMessage, cause);
diff --git a/luni/src/main/java/java/lang/Long.java b/luni/src/main/java/java/lang/Long.java
index 8b592e2..84169af 100644
--- a/luni/src/main/java/java/lang/Long.java
+++ b/luni/src/main/java/java/lang/Long.java
@@ -115,7 +115,6 @@
* Compares two {@code long} values.
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* @since 1.7
- * @hide 1.7
*/
public static int compare(long lhs, long rhs) {
return lhs < rhs ? -1 : (lhs == rhs ? 0 : 1);
diff --git a/luni/src/main/java/java/lang/Math.java b/luni/src/main/java/java/lang/Math.java
index f8d22ed..86df784 100644
--- a/luni/src/main/java/java/lang/Math.java
+++ b/luni/src/main/java/java/lang/Math.java
@@ -54,7 +54,9 @@
* <li>{@code abs(NaN) = NaN}</li>
* </ul>
*/
- public static native double abs(double d);
+ public static double abs(double d) {
+ return Double.longBitsToDouble(Double.doubleToRawLongBits(d) & 0x7fffffffffffffffL);
+ }
/**
* Returns the absolute value of the argument.
@@ -67,7 +69,9 @@
* <li>{@code abs(NaN) = NaN}</li>
* </ul>
*/
- public static native float abs(float f);
+ public static float abs(float f) {
+ return Float.intBitsToFloat(Float.floatToRawIntBits(f) & 0x7fffffff);
+ }
/**
* Returns the absolute value of the argument.
@@ -75,13 +79,17 @@
* If the argument is {@code Integer.MIN_VALUE}, {@code Integer.MIN_VALUE}
* is returned.
*/
- public static native int abs(int i);
+ public static int abs(int i) {
+ return (i >= 0) ? i : -i;
+ }
/**
* Returns the absolute value of the argument. If the argument is {@code
* Long.MIN_VALUE}, {@code Long.MIN_VALUE} is returned.
*/
- public static native long abs(long l);
+ public static long abs(long l) {
+ return (l >= 0) ? l : -l;
+ }
/**
* Returns the closest double approximation of the arc cosine of the
@@ -495,7 +503,9 @@
* Returns the most positive (closest to positive infinity) of the two
* arguments.
*/
- public static native int max(int i1, int i2);
+ public static int max(int i1, int i2) {
+ return i1 > i2 ? i1 : i2;
+ }
/**
* Returns the most positive (closest to positive infinity) of the two
@@ -571,7 +581,9 @@
* Returns the most negative (closest to negative infinity) of the two
* arguments.
*/
- public static native int min(int i1, int i2);
+ public static int min(int i1, int i2) {
+ return i1 < i2 ? i1 : i2;
+ }
/**
* Returns the most negative (closest to negative infinity) of the two
diff --git a/luni/src/main/java/java/lang/NoSuchFieldException.java b/luni/src/main/java/java/lang/NoSuchFieldException.java
index bea6ecb..9cb88d0 100644
--- a/luni/src/main/java/java/lang/NoSuchFieldException.java
+++ b/luni/src/main/java/java/lang/NoSuchFieldException.java
@@ -21,7 +21,7 @@
* Thrown when the VM notices that a program tries to reference,
* on a class or object, a field that does not exist.
*/
-public class NoSuchFieldException extends Exception {
+public class NoSuchFieldException extends ReflectiveOperationException {
private static final long serialVersionUID = -6143714805279938260L;
diff --git a/luni/src/main/java/java/lang/NoSuchMethodException.java b/luni/src/main/java/java/lang/NoSuchMethodException.java
index 7cae49b..568547b 100644
--- a/luni/src/main/java/java/lang/NoSuchMethodException.java
+++ b/luni/src/main/java/java/lang/NoSuchMethodException.java
@@ -21,7 +21,7 @@
* Thrown when the VM notices that a program tries to reference,
* on a class or object, a method that does not exist.
*/
-public class NoSuchMethodException extends Exception {
+public class NoSuchMethodException extends ReflectiveOperationException {
private static final long serialVersionUID = 5034388446362600923L;
diff --git a/luni/src/main/java/java/lang/ReflectiveOperationException.java b/luni/src/main/java/java/lang/ReflectiveOperationException.java
new file mode 100644
index 0000000..835379c
--- /dev/null
+++ b/luni/src/main/java/java/lang/ReflectiveOperationException.java
@@ -0,0 +1,53 @@
+/*
+ * 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 java.lang;
+
+import java.lang.reflect.Array;
+
+/**
+ * Superclass of exceptions related to reflection.
+ *
+ * @since 1.7
+ */
+public class ReflectiveOperationException extends Exception {
+ /**
+ * Constructs a new exception with no detail message.
+ */
+ public ReflectiveOperationException() {
+ }
+
+ /**
+ * Constructs a new exception with the given detail message.
+ */
+ public ReflectiveOperationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new exception with the given cause.
+ */
+ public ReflectiveOperationException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * Constructs a new exception with the given detail message and cause.
+ */
+ public ReflectiveOperationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/luni/src/main/java/java/lang/Runtime.java b/luni/src/main/java/java/lang/Runtime.java
index 5ded981..8538f8a 100644
--- a/luni/src/main/java/java/lang/Runtime.java
+++ b/luni/src/main/java/java/lang/Runtime.java
@@ -47,6 +47,7 @@
import java.util.StringTokenizer;
import libcore.io.IoUtils;
import libcore.io.Libcore;
+import libcore.util.EmptyArray;
import static libcore.io.OsConstants._SC_NPROCESSORS_CONF;
/**
@@ -66,7 +67,22 @@
/**
* Holds the library paths, used for native library lookup.
*/
- private final String[] mLibPaths;
+ private final String[] mLibPaths = initLibPaths();
+
+ private static String[] initLibPaths() {
+ String javaLibraryPath = System.getProperty("java.library.path");
+ if (javaLibraryPath == null) {
+ return EmptyArray.STRING;
+ }
+ String[] paths = javaLibraryPath.split(":");
+ // Add a '/' to the end of each directory so we don't have to do it every time.
+ for (int i = 0; i < paths.length; ++i) {
+ if (!paths[i].endsWith("/")) {
+ paths[i] += "/";
+ }
+ }
+ return paths;
+ }
/**
* Holds the list of threads to run when the VM terminates
@@ -93,19 +109,6 @@
* Prevent this class from being instantiated.
*/
private Runtime() {
- String pathList = System.getProperty("java.library.path", ".");
- String pathSep = System.getProperty("path.separator", ":");
- String fileSep = System.getProperty("file.separator", "/");
-
- mLibPaths = pathList.split(pathSep);
-
- // Add a '/' to the end so we don't have to do the property lookup
- // and concatenation later.
- for (int i = 0; i < mLibPaths.length; i++) {
- if (!mLibPaths[i].endsWith(fileSep)) {
- mLibPaths[i] += fileSep;
- }
- }
}
/**
@@ -480,7 +483,7 @@
* @param stream
* the input stream to localize.
* @return the localized input stream.
- * @deprecated Use {@link InputStreamReader}.
+ * @deprecated Use {@link InputStreamReader} instead.
*/
@Deprecated
public InputStream getLocalizedInputStream(InputStream stream) {
@@ -500,7 +503,7 @@
* @param stream
* the output stream to localize.
* @return the localized output stream.
- * @deprecated Use {@link OutputStreamWriter}.
+ * @deprecated Use {@link OutputStreamWriter} instead.
*/
@Deprecated
public OutputStream getLocalizedOutputStream(OutputStream stream) {
diff --git a/luni/src/main/java/java/lang/SafeVarargs.java b/luni/src/main/java/java/lang/SafeVarargs.java
new file mode 100644
index 0000000..52baa4d
--- /dev/null
+++ b/luni/src/main/java/java/lang/SafeVarargs.java
@@ -0,0 +1,35 @@
+/*
+ * 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 java.lang;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Claims to the compiler that the annotation target does nothing potentially unsafe
+ * to its varargs argument.
+ *
+ * @since 1.7
+ */
+@Documented
+@Retention(value=RetentionPolicy.RUNTIME)
+@Target(value={ElementType.CONSTRUCTOR, ElementType.METHOD})
+public @interface SafeVarargs {
+}
diff --git a/luni/src/main/java/java/lang/SecurityManager.java b/luni/src/main/java/java/lang/SecurityManager.java
index 98e92cc..55ade78 100644
--- a/luni/src/main/java/java/lang/SecurityManager.java
+++ b/luni/src/main/java/java/lang/SecurityManager.java
@@ -30,7 +30,7 @@
*/
public class SecurityManager {
/**
- * @deprecated Use {@link #checkPermission}
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated
protected boolean inCheck;
@@ -64,7 +64,7 @@
public void checkMulticast(InetAddress maddr) { }
/**
- * @deprecated use {@link #checkMulticast(java.net.InetAddress)}
+ * @deprecated use {@link #checkMulticast(java.net.InetAddress)} instead.
*/
@Deprecated public void checkMulticast(InetAddress maddr, byte ttl) { }
@@ -99,41 +99,41 @@
public void checkWrite(String file) { }
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated public boolean getInCheck() { return inCheck; }
protected Class[] getClassContext() { return null; }
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected ClassLoader currentClassLoader() { return null; }
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected int classLoaderDepth() {
return -1;
}
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected Class<?> currentLoadedClass() { return null; }
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected int classDepth(String name) { return -1; }
/**
- * @deprecated Use {@link #checkPermission}.
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected boolean inClass(String name) { return false; }
/**
- * @deprecated Use {@link #checkPermission}
+ * @deprecated Use {@link #checkPermission} instead.
*/
@Deprecated protected boolean inClassLoader() { return false; }
diff --git a/luni/src/main/java/java/lang/Short.java b/luni/src/main/java/java/lang/Short.java
index 1101805..4479c4c 100644
--- a/luni/src/main/java/java/lang/Short.java
+++ b/luni/src/main/java/java/lang/Short.java
@@ -112,9 +112,8 @@
* Compares two {@code short} values.
* @return 0 if lhs = rhs, less than 0 if lhs < rhs, and greater than 0 if lhs > rhs.
* @since 1.7
- * @hide 1.7
*/
- public static int compare(long lhs, long rhs) {
+ public static int compare(short lhs, short rhs) {
return lhs > rhs ? 1 : (lhs < rhs ? -1 : 0);
}
diff --git a/luni/src/main/java/java/lang/System.java b/luni/src/main/java/java/lang/System.java
index 7205ad5..c825118 100644
--- a/luni/src/main/java/java/lang/System.java
+++ b/luni/src/main/java/java/lang/System.java
@@ -51,7 +51,9 @@
import java.util.Properties;
import java.util.Set;
import libcore.icu.ICU;
+import libcore.io.ErrnoException;
import libcore.io.Libcore;
+import libcore.io.StructPasswd;
import libcore.io.StructUtsname;
import libcore.util.ZoneInfoDB;
@@ -179,13 +181,10 @@
public static native long nanoTime();
/**
- * Causes the VM to stop running and the program to exit. If
- * {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
+ * Causes the VM to stop running and the program to exit with the given exit status.
+ * If {@link #runFinalizersOnExit(boolean)} has been previously invoked with a
* {@code true} argument, then all objects will be properly
* garbage-collected and finalized first.
- *
- * @param code
- * the return code.
*/
public static void exit(int code) {
Runtime.getRuntime().exit(code);
@@ -201,30 +200,18 @@
}
/**
- * Returns the value of the environment variable with the given name {@code
- * var}.
- *
- * @param name
- * the name of the environment variable.
- * @return the value of the specified environment variable or {@code null}
- * if no variable exists with the given name.
+ * Returns the value of the environment variable with the given name, or null if no such
+ * variable exists.
*/
public static String getenv(String name) {
- return getenv(name, null);
- }
-
- private static String getenv(String name, String defaultValue) {
if (name == null) {
throw new NullPointerException("name == null");
}
- String value = Libcore.os.getenv(name);
- return (value != null) ? value : defaultValue;
+ return Libcore.os.getenv(name);
}
/**
- * Returns an unmodifiable map of all available environment variables.
- *
- * @return the map representing all environment variables.
+ * Returns an unmodifiable map of all environment variables to their values.
*/
public static Map<String, String> getenv() {
Map<String, String> map = new HashMap<String, String>();
@@ -283,10 +270,21 @@
p.put("java.ext.dirs", "");
p.put("java.version", "0");
- p.put("java.home", getenv("JAVA_HOME", "/system"));
+ // TODO: does this make any sense? Should we just leave java.home unset?
+ String javaHome = getenv("JAVA_HOME");
+ if (javaHome == null) {
+ javaHome = "/system";
+ }
+ p.put("java.home", javaHome);
+ // On Android, each app gets its own temporary directory. This is just a fallback
+ // default, useful only on the host.
p.put("java.io.tmpdir", "/tmp");
- p.put("java.library.path", getenv("LD_LIBRARY_PATH"));
+
+ String ldLibraryPath = getenv("LD_LIBRARY_PATH");
+ if (ldLibraryPath != null) {
+ p.put("java.library.path", ldLibraryPath);
+ }
p.put("java.specification.name", "Dalvik Core Library");
p.put("java.specification.vendor", projectName);
@@ -313,8 +311,13 @@
p.put("user.language", "en");
p.put("user.region", "US");
- p.put("user.home", getenv("HOME", ""));
- p.put("user.name", getenv("USER", ""));
+ try {
+ StructPasswd passwd = Libcore.os.getpwuid(Libcore.os.getuid());
+ p.put("user.home", passwd.pw_dir);
+ p.put("user.name", passwd.pw_name);
+ } catch (ErrnoException exception) {
+ throw new AssertionError(exception);
+ }
StructUtsname info = Libcore.os.uname();
p.put("os.arch", info.machine);
@@ -325,8 +328,7 @@
p.put("android.icu.library.version", ICU.getIcuVersion());
p.put("android.icu.unicode.version", ICU.getUnicodeVersion());
p.put("android.icu.cldr.version", ICU.getCldrVersion());
- // TODO: it would be nice to have this but currently it causes circularity.
- // p.put("android.tzdata.version", ZoneInfoDB.getVersion());
+
parsePropertyAssignments(p, specialProperties());
// Override built-in properties with settings from the command line.
@@ -370,7 +372,7 @@
* <tr><td>java.ext.dirs</td> <td>(Not useful on Android)</td> <td>Empty</td></tr>
* <tr><td>java.home</td> <td>Location of the VM on the file system</td> <td>{@code /system}</td></tr>
* <tr><td>java.io.tmpdir</td> <td>See {@link java.io.File#createTempFile}</td> <td>{@code /sdcard}</td></tr>
- * <tr><td>java.library.path</td> <td>Search path for JNI libraries</td> <td>{@code /system/lib}</td></tr>
+ * <tr><td>java.library.path</td> <td>Search path for JNI libraries</td> <td>{@code /vendor/lib:/system/lib}</td></tr>
* <tr><td>java.vendor</td> <td>Human-readable VM vendor</td> <td>{@code The Android Project}</td></tr>
* <tr><td>java.vendor.url</td> <td>URL for VM vendor's web site</td> <td>{@code http://www.android.com/}</td></tr>
* <tr><td>java.version</td> <td>(Not useful on Android)</td> <td>{@code 0}</td></tr>
@@ -492,7 +494,6 @@
* starts. Later changes to the property will not affect the value returned by this
* method.
* @since 1.7
- * @hide 1.7 - fix documentation references to "line.separator" in Formatter.
*/
public static String lineSeparator() {
return lineSeparator;
@@ -584,7 +585,7 @@
*
* @param flag
* the flag determines if finalization on exit is enabled.
- * @deprecated this method is unsafe.
+ * @deprecated This method is unsafe.
*/
@SuppressWarnings("deprecation")
@Deprecated
diff --git a/luni/src/main/java/java/lang/Throwable.java b/luni/src/main/java/java/lang/Throwable.java
index b20b882..fc9180b 100644
--- a/luni/src/main/java/java/lang/Throwable.java
+++ b/luni/src/main/java/java/lang/Throwable.java
@@ -35,8 +35,8 @@
* circumstances in which the {@code Throwable} was created (basically an error
* message in most cases), and for saving a stack trace (that is, a record of
* the call stack at a particular point in time) which can be printed later.
- * <p>
- * A {@code Throwable} can also include a cause, which is a nested {@code
+ *
+ * <p>A {@code Throwable} can also include a cause, which is a nested {@code
* Throwable} that represents the original problem that led to this {@code
* Throwable}. It is often used for wrapping various types of errors into a
* common {@code Throwable} without losing the detailed original error
@@ -81,63 +81,65 @@
* Constructs a new {@code Throwable} that includes the current stack trace.
*/
public Throwable() {
+ this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
fillInStackTrace();
}
/**
* Constructs a new {@code Throwable} with the current stack trace and the
- * specified detail message.
- *
- * @param detailMessage
- * the detail message for this {@code Throwable}.
+ * given detail message.
*/
public Throwable(String detailMessage) {
- this();
this.detailMessage = detailMessage;
+ this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+ fillInStackTrace();
}
/**
* Constructs a new {@code Throwable} with the current stack trace, the
- * specified detail message and the specified cause.
- *
- * @param detailMessage
- * the detail message for this {@code Throwable}.
- * @param throwable
- * the cause of this {@code Throwable}.
+ * given detail message and cause.
*/
- public Throwable(String detailMessage, Throwable throwable) {
- this();
+ public Throwable(String detailMessage, Throwable cause) {
this.detailMessage = detailMessage;
- cause = throwable;
+ this.cause = cause;
+ this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+ fillInStackTrace();
}
/**
* Constructs a new {@code Throwable} with the current stack trace and the
- * specified cause.
- *
- * @param throwable
- * the cause of this {@code Throwable}.
+ * given cause.
*/
- public Throwable(Throwable throwable) {
- this();
- this.detailMessage = throwable == null ? null : throwable.toString();
- cause = throwable;
+ public Throwable(Throwable cause) {
+ this.detailMessage = cause == null ? null : cause.toString();
+ this.cause = cause;
+ this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+ fillInStackTrace();
}
/**
* Constructs a new {@code Throwable} with the current stack trace, the
* specified detail message and the specified cause.
*
- * @param enableSuppression if false, throwables passed to {@link
- * #addSuppressed(Throwable)} will be silently discarded.
+ * @param enableSuppression if false, {@link #addSuppressed(Throwable)} will be a no-op.
+ * @param writableStackTrace if false, {@link #fillInStackTrace} will not be called,
+ * this object's {@code stackTrace} will be null,
+ * calls to {@link #fillInStackTrace} and {@link #setStackTrace} will be no-ops,
+ * and {@link #getStackTrace} will return a zero-length array.
* @since 1.7
- * @hide 1.7
*/
- protected Throwable(String detailMessage, Throwable throwable, boolean enableSuppression) {
- this(detailMessage, throwable);
+ protected Throwable(String detailMessage, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ this.detailMessage = detailMessage;
+ this.cause = cause;
if (!enableSuppression) {
this.suppressedExceptions = null;
}
+ if (writableStackTrace) {
+ this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
+ fillInStackTrace();
+ } else {
+ this.stackTrace = null;
+ }
}
/**
@@ -157,45 +159,41 @@
* @return this {@code Throwable} instance.
*/
public Throwable fillInStackTrace() {
- // Fill in the intermediate representation
+ if (stackTrace == null) {
+ return this; // writableStackTrace was false.
+ }
+ // Fill in the intermediate representation.
stackState = nativeFillInStackTrace();
- // Mark the full representation as empty
- stackTrace = null;
+ // Mark the full representation as in need of update.
+ stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
return this;
}
/**
- * Returns the extra information message which was provided when this
+ * Returns the detail message which was provided when this
* {@code Throwable} was created. Returns {@code null} if no message was
* provided at creation time.
- *
- * @return this {@code Throwable}'s detail message.
*/
public String getMessage() {
return detailMessage;
}
/**
- * Returns the extra information message which was provided when this
+ * Returns the detail message which was provided when this
* {@code Throwable} was created. Returns {@code null} if no message was
* provided at creation time. Subclasses may override this method to return
* localized text for the message. Android returns the regular detail message.
- *
- * @return this {@code Throwable}'s localized detail message.
*/
public String getLocalizedMessage() {
return getMessage();
}
/**
- * Returns the array of stack trace elements of this {@code Throwable}. Each
+ * Returns a clone of the array of stack trace elements of this {@code Throwable}. Each
* {@code StackTraceElement} represents an entry in the call stack. The
* element at position 0 is the top of the stack, that is, the stack frame
* where this {@code Throwable} is thrown.
*
- * @return a copy of the array of {@code StackTraceElement}s representing
- * the call stack. Changes in the array obtained from this call will
- * not change the call stack stored in this {@code Throwable}.
* @see #printStackTrace()
*/
public StackTraceElement[] getStackTrace() {
@@ -218,6 +216,9 @@
* @see #printStackTrace()
*/
public void setStackTrace(StackTraceElement[] trace) {
+ if (stackTrace == null) {
+ return; // writableStackTrace was false.
+ }
StackTraceElement[] newTrace = trace.clone();
for (int i = 0; i < newTrace.length; i++) {
if (newTrace[i] == null) {
@@ -230,7 +231,6 @@
/**
* Writes a printable representation of this {@code Throwable}'s stack trace
* to the {@code System.err} stream.
- *
*/
public void printStackTrace() {
printStackTrace(System.err);
@@ -239,11 +239,6 @@
/**
* Counts the number of duplicate stack frames, starting from the
* end of the stack.
- *
- * @param currentStack a stack to compare
- * @param parentStack a stack to compare
- *
- * @return the number of duplicate stack frames.
*/
private static int countDuplicates(StackTraceElement[] currentStack,
StackTraceElement[] parentStack) {
@@ -263,25 +258,24 @@
/**
* Returns an array of StackTraceElement. Each StackTraceElement
* represents a entry on the stack.
- *
- * @return an array of StackTraceElement representing the stack
*/
private StackTraceElement[] getInternalStackTrace() {
- if (stackTrace == null) {
+ if (stackTrace == EmptyArray.STACK_TRACE_ELEMENT) {
stackTrace = nativeGetStackTrace(stackState);
- stackState = null; // Clean up intermediate representation
+ stackState = null; // Let go of intermediate representation.
+ return stackTrace;
+ } else if (stackTrace == null) {
+ return EmptyArray.STACK_TRACE_ELEMENT;
+ } else {
+ return stackTrace;
}
- return stackTrace;
}
/**
* Writes a printable representation of this {@code Throwable}'s stack trace
- * to the specified print stream. If the {@code Throwable} contains a
+ * to the given print stream. If the {@code Throwable} contains a
* {@link #getCause() cause}, the method will be invoked recursively for
* the nested {@code Throwable}.
- *
- * @param err
- * the stream to write the stack trace on.
*/
public void printStackTrace(PrintStream err) {
try {
@@ -392,8 +386,6 @@
/**
* Returns the cause of this {@code Throwable}, or {@code null} if there is
* no cause.
- *
- * @return Throwable this {@code Throwable}'s cause.
*/
public Throwable getCause() {
if (cause == this) {
@@ -409,7 +401,6 @@
* @throws IllegalArgumentException if {@code throwable == this}.
* @throws NullPointerException if {@code throwable == null}.
* @since 1.7
- * @hide 1.7
*/
public final void addSuppressed(Throwable throwable) {
if (throwable == this) {
@@ -419,9 +410,9 @@
throw new NullPointerException("throwable == null");
}
if (suppressedExceptions != null) {
- // suppressed exceptions are enabled
+ // Suppressed exceptions are enabled.
if (suppressedExceptions.isEmpty()) {
- // ensure we have somewhere to place suppressed exceptions
+ // Ensure we have somewhere to place suppressed exceptions.
suppressedExceptions = new ArrayList<Throwable>(1);
}
suppressedExceptions.add(throwable);
@@ -432,7 +423,6 @@
* Returns the throwables suppressed by this.
*
* @since 1.7
- * @hide 1.7
*/
public final Throwable[] getSuppressed() {
return (suppressedExceptions != null && !suppressedExceptions.isEmpty())
@@ -441,7 +431,7 @@
}
private void writeObject(ObjectOutputStream out) throws IOException {
- // ensure the stackTrace field is initialized
+ // Ensure the stackTrace field is initialized.
getInternalStackTrace();
out.defaultWriteObject();
}
@@ -450,7 +440,7 @@
in.defaultReadObject();
if (suppressedExceptions != null) {
- // the deserialized list may be unmodifiable, so just create a mutable copy
+ // The deserialized list may be unmodifiable, so just create a mutable copy.
suppressedExceptions = new ArrayList<Throwable>(suppressedExceptions);
}
}
diff --git a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
index a87441f..ee75a0e 100644
--- a/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
+++ b/luni/src/main/java/java/lang/reflect/InvocationTargetException.java
@@ -24,7 +24,7 @@
* @see Method#invoke
* @see Constructor#newInstance
*/
-public class InvocationTargetException extends Exception {
+public class InvocationTargetException extends ReflectiveOperationException {
private static final long serialVersionUID = 4085088731926701167L;
diff --git a/luni/src/main/java/java/lang/reflect/Modifier.java b/luni/src/main/java/java/lang/reflect/Modifier.java
index 225ded1..fdbe3bb 100644
--- a/luni/src/main/java/java/lang/reflect/Modifier.java
+++ b/luni/src/main/java/java/lang/reflect/Modifier.java
@@ -26,20 +26,17 @@
public class Modifier {
/**
- * The {@code int} value representing the {@code public}
- * modifier.
+ * The {@code int} value representing the {@code public} modifier.
*/
public static final int PUBLIC = 0x1;
/**
- * The {@code int} value representing the {@code private}
- * modifier.
+ * The {@code int} value representing the {@code private} modifier.
*/
public static final int PRIVATE = 0x2;
/**
- * The {@code int} value representing the {@code protected}
- * modifier.
+ * The {@code int} value representing the {@code protected} modifier.
*/
public static final int PROTECTED = 0x4;
@@ -54,20 +51,17 @@
public static final int FINAL = 0x10;
/**
- * The {@code int} value representing the {@code synchronized}
- * modifier.
+ * The {@code int} value representing the {@code synchronized} modifier.
*/
public static final int SYNCHRONIZED = 0x20;
/**
- * The {@code int} value representing the {@code volatile}
- * modifier.
+ * The {@code int} value representing the {@code volatile} modifier.
*/
public static final int VOLATILE = 0x40;
/**
- * The {@code int} value representing the {@code transient}
- * modifier.
+ * The {@code int} value representing the {@code transient} modifier.
*/
public static final int TRANSIENT = 0x80;
@@ -77,19 +71,17 @@
public static final int NATIVE = 0x100;
/**
- * The {@code int} value representing the {@code interface}
- * modifier.
+ * The {@code int} value representing the {@code interface} modifier.
*/
public static final int INTERFACE = 0x200;
/**
- * The {@code int} value representing the {@code abstract}
- * modifier.
+ * The {@code int} value representing the {@code abstract} modifier.
*/
public static final int ABSTRACT = 0x400;
/**
- * The {@code int} value representing the {@code strict} modifier.
+ * The {@code int} value representing the {@code strictfp} modifier.
*/
public static final int STRICT = 0x800;
@@ -98,13 +90,25 @@
static final int VARARGS = 0x80;
- static final int SYNTHETIC = 0x1000;
+ /**
+ * @hide
+ */
+ public static final int SYNTHETIC = 0x1000;
static final int ANNOTATION = 0x2000;
static final int ENUM = 0x4000;
/**
+ * Miranda methods are fabrications to reserve virtual method
+ * table slots in abstract classes that implement interfaces
+ * without declaring the abstract methods that the interface would
+ * require they implement.
+ * @hide
+ */
+ public static final int MIRANDA = 0x8000;
+
+ /**
* Constructs a new {@code Modifier} instance.
*/
public Modifier() {
@@ -113,7 +117,6 @@
/**
* Returns a mask of all the modifiers that may be applied to classes.
* @since 1.7
- * @hide 1.7
*/
public static int classModifiers() {
return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | STRICT;
@@ -122,7 +125,6 @@
/**
* Returns a mask of all the modifiers that may be applied to constructors.
* @since 1.7
- * @hide 1.7
*/
public static int constructorModifiers() {
return PUBLIC | PROTECTED | PRIVATE;
@@ -131,7 +133,6 @@
/**
* Returns a mask of all the modifiers that may be applied to fields.
* @since 1.7
- * @hide 1.7
*/
public static int fieldModifiers() {
return PUBLIC | PROTECTED | PRIVATE | STATIC | FINAL | TRANSIENT | VOLATILE;
@@ -140,7 +141,6 @@
/**
* Returns a mask of all the modifiers that may be applied to interfaces.
* @since 1.7
- * @hide 1.7
*/
public static int interfaceModifiers() {
return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | STRICT;
@@ -149,163 +149,90 @@
/**
* Returns a mask of all the modifiers that may be applied to methods.
* @since 1.7
- * @hide 1.7
*/
public static int methodModifiers() {
return PUBLIC | PROTECTED | PRIVATE | ABSTRACT | STATIC | FINAL | SYNCHRONIZED | NATIVE | STRICT;
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * abstract} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * abstract} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #ABSTRACT}.
*/
public static boolean isAbstract(int modifiers) {
return ((modifiers & ABSTRACT) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * final} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * final} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #FINAL}.
*/
public static boolean isFinal(int modifiers) {
return ((modifiers & FINAL) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * interface} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * interface} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #INTERFACE}.
*/
public static boolean isInterface(int modifiers) {
return ((modifiers & INTERFACE) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * native} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * native} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #NATIVE}.
*/
public static boolean isNative(int modifiers) {
return ((modifiers & NATIVE) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * private} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * private} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #PRIVATE}.
*/
public static boolean isPrivate(int modifiers) {
return ((modifiers & PRIVATE) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * protected} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * protected} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #PROTECTED}.
*/
public static boolean isProtected(int modifiers) {
return ((modifiers & PROTECTED) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * public} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * public} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #PUBLIC}.
*/
public static boolean isPublic(int modifiers) {
return ((modifiers & PUBLIC) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * static} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * static} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #STATIC}.
*/
public static boolean isStatic(int modifiers) {
return ((modifiers & STATIC) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * strict} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * strict} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #STRICT}.
*/
public static boolean isStrict(int modifiers) {
return ((modifiers & STRICT) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * synchronized} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * synchronized} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #SYNCHRONIZED}.
*/
public static boolean isSynchronized(int modifiers) {
return ((modifiers & SYNCHRONIZED) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * transient} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * transient} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #TRANSIENT}.
*/
public static boolean isTransient(int modifiers) {
return ((modifiers & TRANSIENT) != 0);
}
/**
- * Indicates whether or not the specified modifiers contain the {@code
- * volatile} modifier.
- *
- * @param modifiers
- * the modifiers to test
- * @return {@code true} if the specified modifiers contain the {@code
- * volatile} modifier, {@code false} otherwise
+ * Returns true if the given modifiers contain {@link #VOLATILE}.
*/
public static boolean isVolatile(int modifiers) {
return ((modifiers & VOLATILE) != 0);
@@ -314,17 +241,10 @@
/**
* 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:
- *
- * {@code public private protected abstract static final transient volatile native synchronized interface strict}
- *
- * @param modifiers
- * the modifiers to print
- * @return a printable representation of the modifiers
+ * specified by the Java Language Specification.
*/
public static java.lang.String toString(int modifiers) {
StringBuilder buf = new StringBuilder();
-
if (isPublic(modifiers)) {
buf.append("public ");
}
diff --git a/luni/src/main/java/java/math/BigDecimal.java b/luni/src/main/java/java/math/BigDecimal.java
index 013809d..03ce8dd 100644
--- a/luni/src/main/java/java/math/BigDecimal.java
+++ b/luni/src/main/java/java/math/BigDecimal.java
@@ -1666,26 +1666,20 @@
}
/**
- * Returns a new {@code BigDecimal} whose value is the absolute value of
+ * Returns a {@code BigDecimal} whose value is the absolute value of
* {@code this}. The scale of the result is the same as the scale of this.
- *
- * @return {@code abs(this)}
*/
public BigDecimal abs() {
return ((signum() < 0) ? negate() : this);
}
/**
- * Returns a new {@code BigDecimal} whose value is the absolute value of
+ * Returns a {@code BigDecimal} whose value is the absolute value of
* {@code this}. The result is rounded according to the passed context
* {@code mc}.
- *
- * @param mc
- * rounding mode and precision for the result of this operation.
- * @return {@code abs(this)}
*/
public BigDecimal abs(MathContext mc) {
- BigDecimal result = abs();
+ BigDecimal result = (signum() < 0) ? negate() : new BigDecimal(getUnscaledValue(), scale);
result.inplaceRound(mc);
return result;
}
diff --git a/luni/src/main/java/java/math/BigInt.java b/luni/src/main/java/java/math/BigInt.java
index 614dbb4..e327a6e 100644
--- a/luni/src/main/java/java/math/BigInt.java
+++ b/luni/src/main/java/java/math/BigInt.java
@@ -24,7 +24,7 @@
final class BigInt {
/* Fields used for the internal representation. */
- transient int bignum = 0;
+ transient long bignum = 0;
@Override protected void finalize() throws Throwable {
try {
@@ -42,53 +42,19 @@
return this.decString();
}
- int getNativeBIGNUM() {
+ long getNativeBIGNUM() {
return this.bignum;
}
- static int consumeErrors(StringBuilder sb) {
- int cnt = 0;
- int e, reason;
- while ((e = NativeBN.ERR_get_error()) != 0) {
- reason = e & 255;
- if (reason == 103) {
- throw new ArithmeticException("BigInteger division by zero");
- }
- if (reason == 108) {
- throw new ArithmeticException("BigInteger not invertible");
- }
- if (reason == 65) {
- throw new OutOfMemoryError();
- }
- sb.append(e).append(": ");
- String s = NativeBN.ERR_error_string(e);
- sb.append(s);
- cnt++;
- }
- return cnt;
- }
-
- private static void Check(boolean success) {
- if (!success) {
- StringBuilder sb = new StringBuilder("(openssl)ERR: ");
- int cnt = consumeErrors(sb);
- if (cnt > 0)
- throw new ArithmeticException(sb.toString());
- }
- }
-
-
private void makeValid() {
if (this.bignum == 0) {
this.bignum = NativeBN.BN_new();
- Check(this.bignum != 0);
}
}
private static BigInt newBigInt() {
BigInt bi = new BigInt();
bi.bignum = NativeBN.BN_new();
- Check(bi.bignum != 0);
return bi;
}
@@ -100,7 +66,7 @@
void putCopy(BigInt from) {
this.makeValid();
- Check(NativeBN.BN_copy(this.bignum, from.bignum));
+ NativeBN.BN_copy(this.bignum, from.bignum);
}
BigInt copy() {
@@ -112,12 +78,12 @@
void putLongInt(long val) {
this.makeValid();
- Check(NativeBN.putLongInt(this.bignum, val));
+ NativeBN.putLongInt(this.bignum, val);
}
void putULongInt(long val, boolean neg) {
this.makeValid();
- Check(NativeBN.putULongInt(this.bignum, val, neg));
+ NativeBN.putULongInt(this.bignum, val, neg);
}
private NumberFormatException invalidBigInteger(String s) {
@@ -128,7 +94,6 @@
String s = checkString(original, 10);
this.makeValid();
int usedLen = NativeBN.BN_dec2bn(this.bignum, s);
- Check((usedLen > 0));
if (usedLen < s.length()) {
throw invalidBigInteger(original);
}
@@ -138,7 +103,6 @@
String s = checkString(original, 16);
this.makeValid();
int usedLen = NativeBN.BN_hex2bn(this.bignum, s);
- Check((usedLen > 0));
if (usedLen < s.length()) {
throw invalidBigInteger(original);
}
@@ -205,17 +169,17 @@
void putBigEndian(byte[] a, boolean neg) {
this.makeValid();
- Check(NativeBN.BN_bin2bn(a, a.length, neg, this.bignum));
+ NativeBN.BN_bin2bn(a, a.length, neg, this.bignum);
}
void putLittleEndianInts(int[] a, boolean neg) {
this.makeValid();
- Check(NativeBN.litEndInts2bn(a, a.length, neg, this.bignum));
+ NativeBN.litEndInts2bn(a, a.length, neg, this.bignum);
}
void putBigEndianTwosComplement(byte[] a) {
this.makeValid();
- Check(NativeBN.twosComp2bn(a, a.length, this.bignum));
+ NativeBN.twosComp2bn(a, a.length, this.bignum);
}
@@ -267,61 +231,59 @@
// n > 0: shift left (multiply)
static BigInt shift(BigInt a, int n) {
BigInt r = newBigInt();
- Check(NativeBN.BN_shift(r.bignum, a.bignum, n));
+ NativeBN.BN_shift(r.bignum, a.bignum, n);
return r;
}
void shift(int n) {
- Check(NativeBN.BN_shift(this.bignum, this.bignum, n));
+ NativeBN.BN_shift(this.bignum, this.bignum, n);
}
void addPositiveInt(int w) {
- Check(NativeBN.BN_add_word(this.bignum, w));
+ NativeBN.BN_add_word(this.bignum, w);
}
void multiplyByPositiveInt(int w) {
- Check(NativeBN.BN_mul_word(this.bignum, w));
+ NativeBN.BN_mul_word(this.bignum, w);
}
static int remainderByPositiveInt(BigInt a, int w) {
- int rem = NativeBN.BN_mod_word(a.bignum, w);
- Check(rem != -1);
- return rem;
+ return NativeBN.BN_mod_word(a.bignum, w);
}
static BigInt addition(BigInt a, BigInt b) {
BigInt r = newBigInt();
- Check(NativeBN.BN_add(r.bignum, a.bignum, b.bignum));
+ NativeBN.BN_add(r.bignum, a.bignum, b.bignum);
return r;
}
void add(BigInt a) {
- Check(NativeBN.BN_add(this.bignum, this.bignum, a.bignum));
+ NativeBN.BN_add(this.bignum, this.bignum, a.bignum);
}
static BigInt subtraction(BigInt a, BigInt b) {
BigInt r = newBigInt();
- Check(NativeBN.BN_sub(r.bignum, a.bignum, b.bignum));
+ NativeBN.BN_sub(r.bignum, a.bignum, b.bignum);
return r;
}
static BigInt gcd(BigInt a, BigInt b) {
BigInt r = newBigInt();
- Check(NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum));
+ NativeBN.BN_gcd(r.bignum, a.bignum, b.bignum);
return r;
}
static BigInt product(BigInt a, BigInt b) {
BigInt r = newBigInt();
- Check(NativeBN.BN_mul(r.bignum, a.bignum, b.bignum));
+ NativeBN.BN_mul(r.bignum, a.bignum, b.bignum);
return r;
}
static BigInt bigExp(BigInt a, BigInt p) {
// Sign of p is ignored!
BigInt r = newBigInt();
- Check(NativeBN.BN_exp(r.bignum, a.bignum, p.bignum));
+ NativeBN.BN_exp(r.bignum, a.bignum, p.bignum);
return r;
}
@@ -335,9 +297,8 @@
// int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
}
- static void division(BigInt dividend, BigInt divisor,
- BigInt quotient, BigInt remainder) {
- int quot, rem;
+ static void division(BigInt dividend, BigInt divisor, BigInt quotient, BigInt remainder) {
+ long quot, rem;
if (quotient != null) {
quotient.makeValid();
quot = quotient.bignum;
@@ -350,37 +311,34 @@
} else {
rem = 0;
}
- Check(NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum));
+ NativeBN.BN_div(quot, rem, dividend.bignum, divisor.bignum);
}
static BigInt modulus(BigInt a, BigInt m) {
// Sign of p is ignored! ?
BigInt r = newBigInt();
- Check(NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum));
+ NativeBN.BN_nnmod(r.bignum, a.bignum, m.bignum);
return r;
}
static BigInt modExp(BigInt a, BigInt p, BigInt m) {
// Sign of p is ignored!
BigInt r = newBigInt();
- Check(NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum));
-
- // OPTIONAL:
- // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
+ NativeBN.BN_mod_exp(r.bignum, a.bignum, p.bignum, m.bignum);
return r;
}
static BigInt modInverse(BigInt a, BigInt m) {
BigInt r = newBigInt();
- Check(NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum));
+ NativeBN.BN_mod_inverse(r.bignum, a.bignum, m.bignum);
return r;
}
static BigInt generatePrimeDefault(int bitLength) {
BigInt r = newBigInt();
- Check(NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0));
+ NativeBN.BN_generate_prime_ex(r.bignum, bitLength, false, 0, 0, 0);
return r;
}
diff --git a/luni/src/main/java/java/math/BigInteger.java b/luni/src/main/java/java/math/BigInteger.java
index 90bf0f6..9470b89 100644
--- a/luni/src/main/java/java/math/BigInteger.java
+++ b/luni/src/main/java/java/math/BigInteger.java
@@ -137,7 +137,7 @@
for (int i = 0; i < numberLength; i++) {
digits[i] = random.nextInt();
}
- // Using only the necessary bits
+ // Clear any extra bits.
digits[numberLength - 1] >>>= (-numBits) & 31;
setJavaRepresentation(sign, numberLength, digits);
}
@@ -147,12 +147,12 @@
/**
* Constructs a random {@code BigInteger} instance in the range {@code [0,
* pow(2, bitLength)-1]} which is probably prime. The probability that the
- * returned {@code BigInteger} is prime is beyond
- * {@code 1 - 1/pow(2, certainty)}.
+ * returned {@code BigInteger} is prime is greater than
+ * {@code 1 - 1/2<sup>certainty</sup>)}.
*
- * <p><b>Implementation Note:</b> the {@code Random} argument is ignored.
- * This implementation uses OpenSSL's {@code bn_rand} as a source of
- * cryptographically strong pseudo-random numbers.
+ * <p><b>Note:</b> the {@code Random} argument is ignored if
+ * {@code bitLength >= 16}, where this implementation will use OpenSSL's
+ * {@code BN_generate_prime_ex} as a source of cryptographically strong pseudo-random numbers.
*
* @param bitLength length of the new {@code BigInteger} in bits.
* @param certainty tolerated primality uncertainty.
@@ -160,11 +160,45 @@
* @see <a href="http://www.openssl.org/docs/crypto/BN_rand.html">
* Specification of random generator used from OpenSSL library</a>
*/
- public BigInteger(int bitLength, int certainty, Random unused) {
+ public BigInteger(int bitLength, int certainty, Random random) {
if (bitLength < 2) {
throw new ArithmeticException("bitLength < 2: " + bitLength);
}
- setBigInt(BigInt.generatePrimeDefault(bitLength));
+ if (bitLength < 16) {
+ // We have to generate short primes ourselves, because OpenSSL bottoms out at 16 bits.
+ int candidate;
+ do {
+ candidate = random.nextInt() & ((1 << bitLength) - 1);
+ candidate |= (1 << (bitLength - 1)); // Set top bit.
+ if (bitLength > 2) {
+ candidate |= 1; // Any prime longer than 2 bits must have the bottom bit set.
+ }
+ } while (!isSmallPrime(candidate));
+ BigInt prime = new BigInt();
+ prime.putULongInt(candidate, false);
+ setBigInt(prime);
+ } else {
+ // We need a loop here to work around an OpenSSL bug; http://b/8588028.
+ do {
+ setBigInt(BigInt.generatePrimeDefault(bitLength));
+ } while (bitLength() != bitLength);
+ }
+ }
+
+ private static boolean isSmallPrime(int x) {
+ if (x == 2) {
+ return true;
+ }
+ if ((x % 2) == 0) {
+ return false;
+ }
+ final int max = (int) Math.sqrt(x);
+ for (int i = 3; i <= max; i += 2) {
+ if ((x % i) == 0) {
+ return false;
+ }
+ }
+ return true;
}
/**
@@ -940,26 +974,27 @@
/**
* Returns a {@code BigInteger} whose value is {@code
- * pow(this, exponent) mod m}. The modulus {@code m} must be positive. The
- * result is guaranteed to be in the interval {@code [0, m)} (0 inclusive,
- * m exclusive). If the exponent is negative, then {@code
- * pow(this.modInverse(m), -exponent) mod m} is computed. The inverse of
- * this only exists if {@code this} is relatively prime to m, otherwise an
- * exception is thrown.
+ * pow(this, exponent) mod modulus}. The modulus must be positive. The
+ * result is guaranteed to be in the interval {@code [0, modulus)}.
+ * If the exponent is negative, then
+ * {@code pow(this.modInverse(modulus), -exponent) mod modulus} is computed.
+ * The inverse of this only exists if {@code this} is relatively prime to the modulus,
+ * otherwise an exception is thrown.
*
- * @param exponent the exponent.
- * @param m the modulus.
- * @throws NullPointerException if {@code m == null} or {@code exponent ==
- * null}.
- * @throws ArithmeticException if {@code m < 0} or if {@code exponent<0} and
- * this is not relatively prime to {@code m}.
+ * @throws NullPointerException if {@code modulus == null} or {@code exponent == null}.
+ * @throws ArithmeticException if {@code modulus < 0} or if {@code exponent < 0} and
+ * not relatively prime to {@code modulus}.
*/
- public BigInteger modPow(BigInteger exponent, BigInteger m) {
- if (m.signum() <= 0) {
- throw new ArithmeticException("m.signum() <= 0");
+ public BigInteger modPow(BigInteger exponent, BigInteger modulus) {
+ if (modulus.signum() <= 0) {
+ throw new ArithmeticException("modulus.signum() <= 0");
}
- BigInteger base = exponent.signum() < 0 ? modInverse(m) : this;
- return new BigInteger(BigInt.modExp(base.getBigInt(), exponent.getBigInt(), m.getBigInt()));
+ int exponentSignum = exponent.signum();
+ if (exponentSignum == 0) { // OpenSSL gets this case wrong; http://b/8574367.
+ return ONE.mod(modulus);
+ }
+ BigInteger base = exponentSignum < 0 ? modInverse(modulus) : this;
+ return new BigInteger(BigInt.modExp(base.getBigInt(), exponent.getBigInt(), modulus.getBigInt()));
}
/**
@@ -983,8 +1018,8 @@
/**
* Tests whether this {@code BigInteger} is probably prime. If {@code true}
- * is returned, then this is prime with a probability beyond
- * {@code 1 - 1/pow(2, certainty)}. If {@code false} is returned, then this
+ * is returned, then this is prime with a probability greater than
+ * {@code 1 - 1/2<sup>certainty</sup>)}. If {@code false} is returned, then this
* is definitely composite. If the argument {@code certainty} <= 0, then
* this method returns true.
*
@@ -1002,7 +1037,7 @@
/**
* Returns the smallest integer x > {@code this} which is probably prime as
* a {@code BigInteger} instance. The probability that the returned {@code
- * BigInteger} is prime is beyond {@code 1 - 1/pow(2, 80)}.
+ * BigInteger} is prime is greater than {@code 1 - 1/2<sup>100</sup>}.
*
* @return smallest integer > {@code this} which is probably prime.
* @throws ArithmeticException if {@code this < 0}.
@@ -1017,17 +1052,14 @@
/**
* Returns a random positive {@code BigInteger} instance in the range {@code
* [0, pow(2, bitLength)-1]} which is probably prime. The probability that
- * the returned {@code BigInteger} is prime is beyond {@code
- * 1 - 1/pow(2, 80)}.
- *
- * <p><b>Implementation Note:</b> Currently {@code random} is ignored.
+ * the returned {@code BigInteger} is prime is greater than {@code 1 - 1/2<sup>100</sup>)}.
*
* @param bitLength length of the new {@code BigInteger} in bits.
* @return probably prime random {@code BigInteger} instance.
* @throws IllegalArgumentException if {@code bitLength < 2}.
*/
- public static BigInteger probablePrime(int bitLength, Random unused) {
- return new BigInteger(bitLength, 100, unused);
+ public static BigInteger probablePrime(int bitLength, Random random) {
+ return new BigInteger(bitLength, 100, random);
}
/* Private Methods */
@@ -1035,8 +1067,6 @@
/**
* Returns the two's complement representation of this BigInteger in a byte
* array.
- *
- * @return two's complement representation of {@code this}
*/
private byte[] twosComplement() {
prepareJavaRepresentation();
diff --git a/luni/src/main/java/java/math/NativeBN.java b/luni/src/main/java/java/math/NativeBN.java
index 95bb2a2..513dafd 100644
--- a/luni/src/main/java/java/math/NativeBN.java
+++ b/luni/src/main/java/java/math/NativeBN.java
@@ -18,148 +18,113 @@
final class NativeBN {
- public static native int ERR_get_error();
- // unsigned long ERR_get_error(void);
-
- public static native String ERR_error_string(int e);
- // char *ERR_error_string(unsigned long e, char *buf);
-
- public static native int BN_new();
+ public static native long BN_new();
// BIGNUM *BN_new(void);
- public static native void BN_free(int a);
+ public static native void BN_free(long a);
// void BN_free(BIGNUM *a);
- public static native int BN_cmp(int a, int b);
+ public static native int BN_cmp(long a, long b);
// int BN_cmp(const BIGNUM *a, const BIGNUM *b);
- public static native boolean BN_copy(int to, int from);
- // Returns boolean success AND NOT result BIGNUM handle!
+ public static native void BN_copy(long to, long from);
// BIGNUM *BN_copy(BIGNUM *to, const BIGNUM *from);
-// public static native int BN_dup(int from);
- // BIGNUM *BN_dup(const BIGNUM *a);
+ public static native void putLongInt(long a, long dw);
+ public static native void putULongInt(long a, long dw, boolean neg);
- public static native boolean putLongInt(int a, long dw);
-
- public static native boolean putULongInt(int a, long dw, boolean neg);
-
- public static native int BN_dec2bn(int a, String str);
+ public static native int BN_dec2bn(long a, String str);
// int BN_dec2bn(BIGNUM **a, const char *str);
- public static native int BN_hex2bn(int a, String str);
+ public static native int BN_hex2bn(long a, String str);
// int BN_hex2bn(BIGNUM **a, const char *str);
- public static native boolean BN_bin2bn(byte[] s, int len, boolean neg, int ret);
- // Returns boolean success AND NOT result BIGNUM handle!
+ public static native void BN_bin2bn(byte[] s, int len, boolean neg, long ret);
// BIGNUM * BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
// BN-Docu: s is taken as unsigned big endian;
// Additional parameter: neg.
- public static native boolean litEndInts2bn(int[] ints, int len, boolean neg, int ret);
+ public static native void litEndInts2bn(int[] ints, int len, boolean neg, long ret);
- public static native boolean twosComp2bn(byte[] s, int len, int ret);
+ public static native void twosComp2bn(byte[] s, int len, long ret);
- public static native long longInt(int a);
+ public static native long longInt(long a);
// unsigned long BN_get_word(BIGNUM *a);
- public static native String BN_bn2dec(int a);
+ public static native String BN_bn2dec(long a);
// char * BN_bn2dec(const BIGNUM *a);
- public static native String BN_bn2hex(int a);
+ public static native String BN_bn2hex(long a);
// char * BN_bn2hex(const BIGNUM *a);
- public static native byte[] BN_bn2bin(int a);
+ public static native byte[] BN_bn2bin(long a);
// Returns result byte[] AND NOT length.
// int BN_bn2bin(const BIGNUM *a, unsigned char *to);
- public static native int[] bn2litEndInts(int a);
+ public static native int[] bn2litEndInts(long a);
- public static native int sign(int a);
+ public static native int sign(long a);
// Returns -1, 0, 1 AND NOT boolean.
// #define BN_is_negative(a) ((a)->neg != 0)
- public static native void BN_set_negative(int b, int n);
+ public static native void BN_set_negative(long b, int n);
// void BN_set_negative(BIGNUM *b, int n);
- public static native int bitLength(int a);
+ public static native int bitLength(long a);
- public static native boolean BN_is_bit_set(int a, int n);
+ public static native boolean BN_is_bit_set(long a, int n);
// int BN_is_bit_set(const BIGNUM *a, int n);
- public static native boolean modifyBit(int a, int n, int op);
- // Returns boolean success.
- // op: 0 = reset; 1 = set; -1 = flip
- // uses BN_set_bit(), BN_clear_bit() and BN_is_bit_set()
-
- public static native boolean BN_shift(int r, int a, int n);
+ public static native void BN_shift(long r, long a, int n);
// int BN_shift(BIGNUM *r, const BIGNUM *a, int n);
- public static native boolean BN_add_word(int a, int w);
+ public static native void BN_add_word(long a, int w);
// ATTENTION: w is treated as unsigned.
// int BN_add_word(BIGNUM *a, BN_ULONG w);
- public static native boolean BN_sub_word(int a, int w);
- // ATTENTION: w is treated as unsigned.
- // int BN_sub_word(BIGNUM *a, BN_ULONG w);
-
- public static native boolean BN_mul_word(int a, int w);
+ public static native void BN_mul_word(long a, int w);
// ATTENTION: w is treated as unsigned.
// int BN_mul_word(BIGNUM *a, BN_ULONG w);
- public static native int BN_div_word(int a, int w);
- // ATTENTION: w is treated as unsigned.
- // BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w);
-
- public static native int BN_mod_word(int a, int w);
+ public static native int BN_mod_word(long a, int w);
// ATTENTION: w is treated as unsigned.
// BN_ULONG BN_mod_word(BIGNUM *a, BN_ULONG w);
- public static native boolean BN_add(int r, int a, int b);
+ public static native void BN_add(long r, long a, long b);
// int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
- public static native boolean BN_sub(int r, int a, int b);
+ public static native void BN_sub(long r, long a, long b);
// int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
- public static native boolean BN_gcd(int r, int a, int b);
+ public static native void BN_gcd(long r, long a, long b);
// int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
- public static native boolean BN_mul(int r, int a, int b);
+ public static native void BN_mul(long r, long a, long b);
// int BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx);
- public static native boolean BN_exp(int r, int a, int p);
+ public static native void BN_exp(long r, long a, long p);
// int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx);
- // OPTIONAL:
-// public static native int BN_sqr(BigInteger r, BigInteger a, BN_CTX ctx);
- // int BN_sqr(BIGNUM *r, const BIGNUM *a,BN_CTX *ctx);
-
- public static native boolean BN_div(int dv, int rem, int m, int d);
+ public static native void BN_div(long dv, long rem, long m, long d);
// int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx);
- public static native boolean BN_nnmod(int r, int a, int m);
+ public static native void BN_nnmod(long r, long a, long m);
// int BN_nnmod(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
- public static native boolean BN_mod_exp(int r, int a, int p, int m);
+ public static native void BN_mod_exp(long r, long a, long p, long m);
// int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx);
- // OPTIONAL:
-// public static native boolean BN_mod_sqr(BigInteger r, BigInteger a, BigInteger m, BN_CTX ctx);
- // int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx);
-
-
- public static native boolean BN_mod_inverse(int ret, int a, int n);
- // Returns boolean success AND NOT result BIGNUM handle!
+ public static native void BN_mod_inverse(long ret, long a, long n);
// BIGNUM * BN_mod_inverse(BIGNUM *ret, const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
- public static native boolean BN_generate_prime_ex(int ret, int bits, boolean safe,
- int add, int rem, int cb);
+ public static native void BN_generate_prime_ex(long ret, int bits, boolean safe,
+ long add, long rem, long cb);
// int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
// const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb);
- public static native boolean BN_is_prime_ex(int p, int nchecks, int cb);
+ public static native boolean BN_is_prime_ex(long p, int nchecks, long cb);
// int BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, BN_GENCB *cb);
}
diff --git a/luni/src/main/java/java/net/DatagramSocket.java b/luni/src/main/java/java/net/DatagramSocket.java
index 790ebc9..49f141a 100644
--- a/luni/src/main/java/java/net/DatagramSocket.java
+++ b/luni/src/main/java/java/net/DatagramSocket.java
@@ -17,10 +17,12 @@
package java.net;
+import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
import java.nio.channels.DatagramChannel;
import libcore.io.ErrnoException;
+import libcore.io.IoBridge;
import libcore.io.Libcore;
import static libcore.io.OsConstants.*;
@@ -32,7 +34,7 @@
* @see DatagramPacket
* @see DatagramSocketImplFactory
*/
-public class DatagramSocket {
+public class DatagramSocket implements Closeable {
DatagramSocketImpl impl;
@@ -150,20 +152,15 @@
}
/**
- * Gets the {@code InetAddress} instance representing the bound local
- * address of this UDP datagram socket.
- *
- * @return the local address to which this socket is bound to or {@code
- * null} if this socket is closed.
+ * Returns the local address to which this socket is bound,
+ * or {@code null} if this socket is closed.
*/
public InetAddress getLocalAddress() {
- if (isClosed()) {
+ try {
+ return IoBridge.getSocketLocalAddress(impl.fd);
+ } catch (SocketException ex) {
return null;
}
- if (!isBound()) {
- return Inet4Address.ANY;
- }
- return impl.getLocalAddress();
}
/**
diff --git a/luni/src/main/java/java/net/DatagramSocketImpl.java b/luni/src/main/java/java/net/DatagramSocketImpl.java
index 6e706c3..097eb17 100644
--- a/luni/src/main/java/java/net/DatagramSocketImpl.java
+++ b/luni/src/main/java/java/net/DatagramSocketImpl.java
@@ -19,7 +19,6 @@
import java.io.FileDescriptor;
import java.io.IOException;
-import libcore.io.IoBridge;
/**
* The abstract superclass for datagram and multicast socket implementations.
@@ -82,13 +81,6 @@
}
/**
- * Returns the local address to which the socket is bound.
- */
- InetAddress getLocalAddress() {
- return IoBridge.getSocketLocalAddress(fd);
- }
-
- /**
* Returns the local port to which this socket is bound.
*/
protected int getLocalPort() {
@@ -102,7 +94,7 @@
* @throws IOException
* if an error occurs while getting the time-to-live option
* value.
- * @deprecated Replaced by {@link #getTimeToLive}
+ * @deprecated Use {@link #getTimeToLive} instead.
* @see #getTimeToLive()
*/
@Deprecated
@@ -233,7 +225,7 @@
* <= 255.
* @throws IOException
* if an error occurs while setting the option.
- * @deprecated Replaced by {@link #setTimeToLive}
+ * @deprecated Use {@link #setTimeToLive} instead.
* @see #setTimeToLive(int)
*/
@Deprecated
diff --git a/luni/src/main/java/java/net/ExtendedResponseCache.java b/luni/src/main/java/java/net/ExtendedResponseCache.java
deleted file mode 100644
index a70e734..0000000
--- a/luni/src/main/java/java/net/ExtendedResponseCache.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.net;
-
-/**
- * A response cache that supports statistics tracking and updating stored
- * responses. Implementations of {@link ResponseCache} should implement this
- * interface to receive additional support from the HTTP engine.
- *
- * @hide
- */
-public interface ExtendedResponseCache {
-
- /*
- * This hidden interface is defined in a non-hidden package (java.net) so
- * its @hide tag will be parsed by Doclava. This hides this interface from
- * implementing classes' documentation.
- */
-
- /**
- * Track an HTTP response being satisfied by {@code source}.
- * @hide
- */
- void trackResponse(ResponseSource source);
-
- /**
- * Track an conditional GET that was satisfied by this cache.
- * @hide
- */
- void trackConditionalCacheHit();
-
- /**
- * Updates stored HTTP headers using a hit on a conditional GET.
- * @hide
- */
- void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection);
-}
diff --git a/luni/src/main/java/java/net/HttpURLConnection.java b/luni/src/main/java/java/net/HttpURLConnection.java
index 2023887..d6b2435 100644
--- a/luni/src/main/java/java/net/HttpURLConnection.java
+++ b/luni/src/main/java/java/net/HttpURLConnection.java
@@ -20,7 +20,6 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
-import libcore.net.http.HttpEngine;
/**
* An {@link URLConnection} for HTTP (<a
@@ -257,19 +256,20 @@
* request/response pair. Instances of this class are not thread safe.
*/
public abstract class HttpURLConnection extends URLConnection {
+ private static final int DEFAULT_CHUNK_LENGTH = 1024;
/**
* The subset of HTTP methods that the user may select via {@link
* #setRequestMethod(String)}.
*/
private static final String[] PERMITTED_USER_METHODS = {
- HttpEngine.OPTIONS,
- HttpEngine.GET,
- HttpEngine.HEAD,
- HttpEngine.POST,
- HttpEngine.PUT,
- HttpEngine.DELETE,
- HttpEngine.TRACE
+ "OPTIONS",
+ "GET",
+ "HEAD",
+ "POST",
+ "PUT",
+ "DELETE",
+ "TRACE"
// Note: we don't allow users to specify "CONNECT"
};
@@ -277,7 +277,7 @@
* The HTTP request method of this {@code HttpURLConnection}. The default
* value is {@code "GET"}.
*/
- protected String method = HttpEngine.GET;
+ protected String method = "GET";
/**
* The status code of the response obtained from the HTTP request. The
@@ -312,12 +312,20 @@
protected int chunkLength = -1;
/**
- * If using HTTP fixed-length streaming mode this parameter defines the
- * fixed length of content. Default value is {@code -1} that means the
- * fixed-length streaming mode is disabled.
+ * The byte count in the request body if it is both known and streamed; and
+ * -1 otherwise. If the byte count exceeds {@link Integer#MAX_VALUE} (2 GiB)
+ * then the value of this field will be {@link Integer#MAX_VALUE}. In that
+ * case use {@link #fixedContentLengthLong} to access the exact byte count.
*/
protected int fixedContentLength = -1;
+ /**
+ * The byte count in the request body if it is both known and streamed; and
+ * -1 otherwise. Prefer this field over the {@code int}-valued {@code
+ * fixedContentLength} on platforms that support both.
+ */
+ protected long fixedContentLengthLong = -1;
+
// 2XX: generally "OK"
// 3XX: relocation/redirect
// 4XX: client error
@@ -475,7 +483,7 @@
/**
* Numeric status code, 500: Internal error
*
- * @deprecated Use {@link #HTTP_INTERNAL_ERROR}
+ * @deprecated Use {@link #HTTP_INTERNAL_ERROR} instead.
*/
@Deprecated
public static final int HTTP_SERVER_ERROR = 500;
@@ -737,9 +745,8 @@
}
/**
- * If the length of a HTTP request body is known ahead, sets fixed length to
- * enable streaming without buffering. Sets after connection will cause an
- * exception.
+ * Configures this connection to stream the request body with the known
+ * fixed byte count of {@code contentLength}.
*
* @see #setChunkedStreamingMode
* @param contentLength
@@ -748,8 +755,9 @@
* if already connected or another mode already set.
* @throws IllegalArgumentException
* if {@code contentLength} is less than zero.
+ * @since 1.7
*/
- public void setFixedLengthStreamingMode(int contentLength) {
+ public void setFixedLengthStreamingMode(long contentLength) {
if (super.connected) {
throw new IllegalStateException("Already connected");
}
@@ -759,7 +767,16 @@
if (contentLength < 0) {
throw new IllegalArgumentException("contentLength < 0");
}
- this.fixedContentLength = contentLength;
+ this.fixedContentLength = (int) Math.min(contentLength, Integer.MAX_VALUE);
+ this.fixedContentLengthLong = contentLength;
+ }
+
+ /**
+ * Equivalent to {@code setFixedLengthStreamingMode((long) contentLength)},
+ * but available on earlier versions of Android and limited to 2 GiB.
+ */
+ public void setFixedLengthStreamingMode(int contentLength) {
+ setFixedLengthStreamingMode((long) contentLength);
}
/**
@@ -787,7 +804,7 @@
throw new IllegalStateException("Already in fixed-length mode");
}
if (chunkLength <= 0) {
- this.chunkLength = HttpEngine.DEFAULT_CHUNK_LENGTH;
+ this.chunkLength = DEFAULT_CHUNK_LENGTH;
} else {
this.chunkLength = chunkLength;
}
diff --git a/luni/src/main/java/java/net/InetAddress.java b/luni/src/main/java/java/net/InetAddress.java
index bbe34c2..98ad098 100644
--- a/luni/src/main/java/java/net/InetAddress.java
+++ b/luni/src/main/java/java/net/InetAddress.java
@@ -495,7 +495,6 @@
/**
* Returns the IPv6 loopback address {@code ::1} or the IPv4 loopback address {@code 127.0.0.1}.
* @since 1.7
- * @hide 1.7
*/
public static InetAddress getLoopbackAddress() {
return Inet6Address.LOOPBACK;
diff --git a/luni/src/main/java/java/net/InetSocketAddress.java b/luni/src/main/java/java/net/InetSocketAddress.java
index 4f4a348..a366133 100644
--- a/luni/src/main/java/java/net/InetSocketAddress.java
+++ b/luni/src/main/java/java/net/InetSocketAddress.java
@@ -145,8 +145,9 @@
}
/**
- * Returns the hostname, doing a reverse lookup on the {@code InetAddress} if no
- * hostname string was provided at construction time.
+ * Returns the hostname, doing a reverse DNS lookup on the {@code InetAddress} if no
+ * hostname string was provided at construction time. Use {@link #getHostString} to
+ * avoid the reverse DNS lookup.
*/
public final String getHostName() {
return (addr != null) ? addr.getHostName() : hostname;
@@ -156,7 +157,6 @@
* Returns the hostname if known, or the result of {@code InetAddress.getHostAddress}.
* Unlike {@link #getHostName}, this method will never cause a DNS lookup.
* @since 1.7
- * @hide 1.7 - remember to add a link in the getHostName documentation!
*/
public final String getHostString() {
return (hostname != null) ? hostname : addr.getHostAddress();
diff --git a/luni/src/main/java/java/net/InetUnixAddress.java b/luni/src/main/java/java/net/InetUnixAddress.java
index 95bb097..44b9cba 100644
--- a/luni/src/main/java/java/net/InetUnixAddress.java
+++ b/luni/src/main/java/java/net/InetUnixAddress.java
@@ -16,7 +16,7 @@
package java.net;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import static libcore.io.OsConstants.*;
@@ -29,7 +29,7 @@
* Constructs an AF_UNIX InetAddress for the given path.
*/
public InetUnixAddress(String path) {
- this(path.getBytes(Charsets.UTF_8));
+ this(path.getBytes(StandardCharsets.UTF_8));
}
/**
@@ -43,6 +43,6 @@
* Returns a string form of this InetAddress.
*/
@Override public String toString() {
- return "InetUnixAddress[" + new String(ipaddress, Charsets.UTF_8) + "]";
+ return "InetUnixAddress[" + new String(ipaddress, StandardCharsets.UTF_8) + "]";
}
}
diff --git a/luni/src/main/java/java/net/MulticastSocket.java b/luni/src/main/java/java/net/MulticastSocket.java
index 498a132..6f4a582 100644
--- a/luni/src/main/java/java/net/MulticastSocket.java
+++ b/luni/src/main/java/java/net/MulticastSocket.java
@@ -127,7 +127,7 @@
* Returns the time-to-live (TTL) for multicast packets sent on this socket.
*
* @throws IOException if an error occurs.
- * @deprecated Replaced by {@link #getTimeToLive}
+ * @deprecated Use {@link #getTimeToLive} instead.
*/
@Deprecated
public byte getTTL() throws IOException {
@@ -239,7 +239,7 @@
* deprecated because it modifies the TTL socket option for this socket twice on each call.
*
* @throws IOException if an error occurs.
- * @deprecated use {@link #setTimeToLive}.
+ * @deprecated Use {@link #setTimeToLive} instead.
*/
@Deprecated
public void send(DatagramPacket packet, byte ttl) throws IOException {
@@ -314,7 +314,7 @@
* Valid TTL values are between 0 and 255 inclusive.
*
* @throws IOException if an error occurs.
- * @deprecated Replaced by {@link #setTimeToLive}
+ * @deprecated Use {@link #setTimeToLive} instead.
*/
@Deprecated
public void setTTL(byte ttl) throws IOException {
diff --git a/luni/src/main/java/java/net/NetworkInterface.java b/luni/src/main/java/java/net/NetworkInterface.java
index ad81f32..b35424d 100644
--- a/luni/src/main/java/java/net/NetworkInterface.java
+++ b/luni/src/main/java/java/net/NetworkInterface.java
@@ -67,8 +67,7 @@
/**
* Returns the index for the network interface, or -1 if unknown.
- *
- * @hide 1.7
+ * @since 1.7
*/
public int getIndex() {
return interfaceIndex;
@@ -250,7 +249,7 @@
* interface has this index.
*
* @throws SocketException if an error occurs.
- * @hide 1.7
+ * @since 1.7
*/
public static NetworkInterface getByIndex(int index) throws SocketException {
String name = Libcore.os.if_indextoname(index);
diff --git a/luni/src/main/java/java/net/PlainSocketImpl.java b/luni/src/main/java/java/net/PlainSocketImpl.java
index e247ac3..18942d6 100644
--- a/luni/src/main/java/java/net/PlainSocketImpl.java
+++ b/luni/src/main/java/java/net/PlainSocketImpl.java
@@ -236,8 +236,8 @@
return Streams.readSingleByte(this);
}
- @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException {
- return socketImpl.read(buffer, offset, byteCount);
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ return socketImpl.read(buffer, byteOffset, byteCount);
}
}
diff --git a/luni/src/main/java/java/net/ResponseSource.java b/luni/src/main/java/java/net/ResponseSource.java
deleted file mode 100644
index fb974e9..0000000
--- a/luni/src/main/java/java/net/ResponseSource.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.net;
-
-/**
- * Where the HTTP client should look for a response.
- *
- * @hide
- */
-public enum ResponseSource {
-
- /**
- * Return the response from the cache immediately.
- */
- CACHE,
-
- /**
- * Make a conditional request to the host, returning the cache response if
- * the cache is valid and the network response otherwise.
- */
- CONDITIONAL_CACHE,
-
- /**
- * Return the response from the network.
- */
- NETWORK;
-
- public boolean requiresConnection() {
- return this == CONDITIONAL_CACHE || this == NETWORK;
- }
-}
diff --git a/luni/src/main/java/java/net/ServerSocket.java b/luni/src/main/java/java/net/ServerSocket.java
index ba8d6269..399511f 100644
--- a/luni/src/main/java/java/net/ServerSocket.java
+++ b/luni/src/main/java/java/net/ServerSocket.java
@@ -17,6 +17,7 @@
package java.net;
+import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.ServerSocketChannel;
@@ -26,7 +27,7 @@
* appropriate reply. The actual tasks that a server socket must accomplish are
* implemented by an internal {@code SocketImpl} instance.
*/
-public class ServerSocket {
+public class ServerSocket implements Closeable {
/**
* The RI specifies that where the caller doesn't give an explicit backlog,
* the default is 50. The OS disagrees, so we need to explicitly call listen(2).
diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java
index 2d80586..36fdf28 100644
--- a/luni/src/main/java/java/net/Socket.java
+++ b/luni/src/main/java/java/net/Socket.java
@@ -17,6 +17,7 @@
package java.net;
+import java.io.Closeable;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
@@ -27,7 +28,7 @@
/**
* Provides a client-side TCP socket.
*/
-public class Socket {
+public class Socket implements Closeable {
private static SocketImplFactory factory;
final SocketImpl impl;
@@ -941,12 +942,12 @@
*
* @see ServerSocket#implAccept
*/
- void accepted() {
+ void accepted() throws SocketException {
isCreated = isBound = isConnected = true;
cacheLocalAddress();
}
- private void cacheLocalAddress() {
+ private void cacheLocalAddress() throws SocketException {
this.localAddress = IoBridge.getSocketLocalAddress(impl.fd);
}
diff --git a/luni/src/main/java/java/net/Socks4Message.java b/luni/src/main/java/java/net/Socks4Message.java
index c193520..f7b190d 100644
--- a/luni/src/main/java/java/net/Socks4Message.java
+++ b/luni/src/main/java/java/net/Socks4Message.java
@@ -18,7 +18,7 @@
package java.net;
import java.nio.ByteOrder;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import libcore.io.Memory;
class Socks4Message {
@@ -188,7 +188,7 @@
while (index < lastIndex && (buffer[index] != 0)) {
index++;
}
- return new String(buffer, offset, index - offset, Charsets.ISO_8859_1);
+ return new String(buffer, offset, index - offset, StandardCharsets.ISO_8859_1);
}
/**
@@ -202,7 +202,7 @@
* Put a string into the buffer at the offset given.
*/
private void setString(int offset, int maxLength, String theString) {
- byte[] stringBytes = theString.getBytes(Charsets.ISO_8859_1);
+ byte[] stringBytes = theString.getBytes(StandardCharsets.ISO_8859_1);
int length = Math.min(stringBytes.length, maxLength);
System.arraycopy(stringBytes, 0, buffer, offset, length);
buffer[offset + length] = 0;
diff --git a/luni/src/main/java/java/net/URL.java b/luni/src/main/java/java/net/URL.java
index 9d44498..dd487bc 100644
--- a/luni/src/main/java/java/net/URL.java
+++ b/luni/src/main/java/java/net/URL.java
@@ -24,8 +24,6 @@
import java.io.Serializable;
import java.util.Hashtable;
import java.util.jar.JarFile;
-import libcore.net.http.HttpHandler;
-import libcore.net.http.HttpsHandler;
import libcore.net.url.FileHandler;
import libcore.net.url.FtpHandler;
import libcore.net.url.JarHandler;
@@ -427,9 +425,19 @@
} else if (protocol.equals("ftp")) {
streamHandler = new FtpHandler();
} else if (protocol.equals("http")) {
- streamHandler = new HttpHandler();
+ try {
+ String name = "com.android.okhttp.HttpHandler";
+ streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
} else if (protocol.equals("https")) {
- streamHandler = new HttpsHandler();
+ try {
+ String name = "com.android.okhttp.HttpsHandler";
+ streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
+ } catch (Exception e) {
+ throw new AssertionError(e);
+ }
} else if (protocol.equals("jar")) {
streamHandler = new JarHandler();
}
diff --git a/luni/src/main/java/java/net/URLClassLoader.java b/luni/src/main/java/java/net/URLClassLoader.java
index efb7531..88d2e25 100644
--- a/luni/src/main/java/java/net/URLClassLoader.java
+++ b/luni/src/main/java/java/net/URLClassLoader.java
@@ -26,7 +26,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.SecureClassLoader;
@@ -76,7 +76,7 @@
String parentURLString = getParentURL(url).toExternalForm();
String prefix = "jar:" + parentURLString + "/";
is = jf.getInputStream(indexEntry);
- in = new BufferedReader(new InputStreamReader(is, Charsets.UTF_8));
+ in = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
HashMap<String, ArrayList<URL>> pre_map = new HashMap<String, ArrayList<URL>>();
// Ignore the 2 first lines (index version)
if (in.readLine() == null) return null;
diff --git a/luni/src/main/java/java/net/URLConnection.java b/luni/src/main/java/java/net/URLConnection.java
index 18a264e..74c15ce 100644
--- a/luni/src/main/java/java/net/URLConnection.java
+++ b/luni/src/main/java/java/net/URLConnection.java
@@ -347,7 +347,7 @@
/**
* Returns null.
*
- * @deprecated Use {@link #getRequestProperty}
+ * @deprecated Use {@link #getRequestProperty} instead.
*/
@Deprecated
public static String getDefaultRequestProperty(String field) {
@@ -829,7 +829,7 @@
/**
* Does nothing.
*
- * @deprecated Use {@link URLConnection#setRequestProperty(String, String)}.
+ * @deprecated Use {@link URLConnection#setRequestProperty(String, String)} instead.
*/
@Deprecated
public static void setDefaultRequestProperty(String field, String value) {
diff --git a/luni/src/main/java/java/net/URLDecoder.java b/luni/src/main/java/java/net/URLDecoder.java
index f21de7d..23dd8d0 100644
--- a/luni/src/main/java/java/net/URLDecoder.java
+++ b/luni/src/main/java/java/net/URLDecoder.java
@@ -38,7 +38,7 @@
* @param s
* the encoded string.
* @return the decoded clear-text representation of the given string.
- * @deprecated use {@link #decode(String, String)} instead.
+ * @deprecated Use {@link #decode(String, String)} instead.
*/
@Deprecated
public static String decode(String s) {
diff --git a/luni/src/main/java/java/net/URLEncoder.java b/luni/src/main/java/java/net/URLEncoder.java
index 5dd85b0..0f94907 100644
--- a/luni/src/main/java/java/net/URLEncoder.java
+++ b/luni/src/main/java/java/net/URLEncoder.java
@@ -19,7 +19,7 @@
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import libcore.net.UriCodec;
/**
@@ -43,11 +43,11 @@
/**
* Equivalent to {@code encode(s, "UTF-8")}.
*
- * @deprecated use {@link #encode(String, String)} instead.
+ * @deprecated Use {@link #encode(String, String)} instead.
*/
@Deprecated
public static String encode(String s) {
- return ENCODER.encode(s, Charsets.UTF_8);
+ return ENCODER.encode(s, StandardCharsets.UTF_8);
}
/**
diff --git a/luni/src/main/java/java/net/URLStreamHandler.java b/luni/src/main/java/java/net/URLStreamHandler.java
index 4a04b6f..8a6c264 100644
--- a/luni/src/main/java/java/net/URLStreamHandler.java
+++ b/luni/src/main/java/java/net/URLStreamHandler.java
@@ -222,7 +222,7 @@
* the file component.
* @param ref
* the reference.
- * @deprecated use setURL(URL, String String, int, String, String, String,
+ * @deprecated Use setURL(URL, String String, int, String, String, String,
* String, String) instead.
*/
@Deprecated
diff --git a/luni/src/main/java/java/nio/ByteBuffer.java b/luni/src/main/java/java/nio/ByteBuffer.java
index cd39a53..324369a 100644
--- a/luni/src/main/java/java/nio/ByteBuffer.java
+++ b/luni/src/main/java/java/nio/ByteBuffer.java
@@ -125,7 +125,7 @@
* @exception UnsupportedOperationException
* if this buffer is not based on an array.
*/
- public final byte[] array() {
+ @Override public final byte[] array() {
return protectedArray();
}
@@ -142,7 +142,7 @@
* @exception UnsupportedOperationException
* if this buffer is not based on an array.
*/
- public final int arrayOffset() {
+ @Override public final int arrayOffset() {
return protectedArrayOffset();
}
@@ -290,7 +290,7 @@
* @exception ClassCastException
* if {@code other} is not a byte buffer.
*/
- public int compareTo(ByteBuffer otherBuffer) {
+ @Override public int compareTo(ByteBuffer otherBuffer) {
int compareRemaining = (remaining() < otherBuffer.remaining()) ? remaining()
: otherBuffer.remaining();
int thisPos = position;
@@ -592,7 +592,7 @@
*/
public abstract short getShort(int index);
- public final boolean hasArray() {
+ @Override public final boolean hasArray() {
return protectedHasArray();
}
@@ -617,7 +617,7 @@
*
* @return {@code true} if this buffer is direct, {@code false} otherwise.
*/
- public abstract boolean isDirect();
+ @Override public abstract boolean isDirect();
/**
* Returns the byte order used by this buffer when converting bytes from/to
diff --git a/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java b/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
index ef5c52d..16d0688 100644
--- a/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
+++ b/luni/src/main/java/java/nio/ByteBufferAsCharBuffer.java
@@ -176,8 +176,7 @@
return result;
}
- @Override
- public CharSequence subSequence(int start, int end) {
+ @Override public CharBuffer subSequence(int start, int end) {
checkStartEndRemaining(start, end);
CharBuffer result = duplicate();
result.limit(position + end);
diff --git a/luni/src/main/java/java/nio/CharArrayBuffer.java b/luni/src/main/java/java/nio/CharArrayBuffer.java
index 43a75a6..245a799 100644
--- a/luni/src/main/java/java/nio/CharArrayBuffer.java
+++ b/luni/src/main/java/java/nio/CharArrayBuffer.java
@@ -124,7 +124,7 @@
return ByteOrder.nativeOrder();
}
- @Override public final CharSequence subSequence(int start, int end) {
+ @Override public final CharBuffer subSequence(int start, int end) {
checkStartEndRemaining(start, end);
CharBuffer result = duplicate();
result.limit(position + end);
diff --git a/luni/src/main/java/java/nio/CharBuffer.java b/luni/src/main/java/java/nio/CharBuffer.java
index 5c6f0fc..57070a0 100644
--- a/luni/src/main/java/java/nio/CharBuffer.java
+++ b/luni/src/main/java/java/nio/CharBuffer.java
@@ -632,7 +632,7 @@
* @exception IndexOutOfBoundsException
* if either {@code start} or {@code end} is invalid.
*/
- public abstract CharSequence subSequence(int start, int end);
+ public abstract CharBuffer subSequence(int start, int end);
/**
* Returns a string representing the current remaining chars of this buffer.
diff --git a/luni/src/main/java/java/nio/CharSequenceAdapter.java b/luni/src/main/java/java/nio/CharSequenceAdapter.java
index 12bac31..f686827 100644
--- a/luni/src/main/java/java/nio/CharSequenceAdapter.java
+++ b/luni/src/main/java/java/nio/CharSequenceAdapter.java
@@ -139,8 +139,7 @@
return new CharSequenceAdapter(sequence.subSequence(position, limit));
}
- @Override
- public CharSequence subSequence(int start, int end) {
+ @Override public CharBuffer subSequence(int start, int end) {
checkStartEndRemaining(start, end);
CharSequenceAdapter result = copy(this);
result.position = position + start;
diff --git a/luni/src/main/java/java/nio/DatagramChannelImpl.java b/luni/src/main/java/java/nio/DatagramChannelImpl.java
index a23010e..39f2128 100644
--- a/luni/src/main/java/java/nio/DatagramChannelImpl.java
+++ b/luni/src/main/java/java/nio/DatagramChannelImpl.java
@@ -98,13 +98,6 @@
}
/**
- * Returns the local address to which the socket is bound.
- */
- InetAddress getLocalAddress() {
- return IoBridge.getSocketLocalAddress(fd);
- }
-
- /**
* @see java.nio.channels.DatagramChannel#isConnected()
*/
@Override
@@ -266,6 +259,7 @@
if (sendCount > 0) {
source.position(oldPosition + sendCount);
}
+ isBound = true;
} finally {
end(sendCount >= 0);
}
@@ -420,9 +414,7 @@
}
@Override protected void implConfigureBlocking(boolean blocking) throws IOException {
- synchronized (blockingLock()) {
- IoUtils.setBlocking(fd, blocking);
- }
+ IoUtils.setBlocking(fd, blocking);
}
/*
@@ -514,12 +506,12 @@
return channelImpl.connectAddress.getAddress();
}
- /**
- * @see java.net.DatagramSocket#getLocalAddress()
- */
- @Override
- public InetAddress getLocalAddress() {
- return channelImpl.getLocalAddress();
+ @Override public InetAddress getLocalAddress() {
+ try {
+ return IoBridge.getSocketLocalAddress(channelImpl.fd);
+ } catch (SocketException ex) {
+ return null;
+ }
}
/**
diff --git a/luni/src/main/java/java/nio/FileChannelImpl.java b/luni/src/main/java/java/nio/FileChannelImpl.java
index 14e06b7..a1be7fb 100644
--- a/luni/src/main/java/java/nio/FileChannelImpl.java
+++ b/luni/src/main/java/java/nio/FileChannelImpl.java
@@ -234,13 +234,17 @@
// and we only care about making our backing file longer here.
try {
Libcore.os.ftruncate(fd, position + size);
- } catch (ErrnoException errnoException) {
+ } catch (ErrnoException ftruncateException) {
// EINVAL can be thrown if we're dealing with non-regular
// files, for example, character devices such as /dev/zero.
// In those cases, we ignore the failed truncation and
// continue on.
- if (errnoException.errno != EINVAL) {
- throw errnoException.rethrowAsIOException();
+ try {
+ if (S_ISREG(Libcore.os.fstat(fd).st_mode) || ftruncateException.errno != EINVAL) {
+ throw ftruncateException.rethrowAsIOException();
+ }
+ } catch (ErrnoException fstatException) {
+ throw fstatException.rethrowAsIOException();
}
}
}
diff --git a/luni/src/main/java/java/nio/SelectionKeyImpl.java b/luni/src/main/java/java/nio/SelectionKeyImpl.java
index 694770e..db171b8 100644
--- a/luni/src/main/java/java/nio/SelectionKeyImpl.java
+++ b/luni/src/main/java/java/nio/SelectionKeyImpl.java
@@ -87,11 +87,13 @@
return selector;
}
- /*
- * package private method for setting the ready operation by selector
+ /**
+ * Allows SelectorImpl to set the ready operations.
*/
void setReadyOps(int readyOps) {
- this.readyOps = readyOps;
+ // We mask here (rather than assert, say) so that SelectorImpl doesn't have to worry
+ // about what operations a key is interested in. SelectorImpl is already too complicated.
+ this.readyOps = readyOps & interestOps;
}
private void checkValid() {
diff --git a/luni/src/main/java/java/nio/SelectorImpl.java b/luni/src/main/java/java/nio/SelectorImpl.java
index 02fdf54..41a2a52 100644
--- a/luni/src/main/java/java/nio/SelectorImpl.java
+++ b/luni/src/main/java/java/nio/SelectorImpl.java
@@ -166,13 +166,13 @@
synchronized (unmodifiableKeys) {
synchronized (selectedKeys) {
doCancel();
- boolean isBlock = (timeout != 0);
+ boolean isBlocking = (timeout != 0);
synchronized (keysLock) {
preparePollFds();
}
int rc = -1;
try {
- if (isBlock) {
+ if (isBlocking) {
begin();
}
try {
@@ -183,7 +183,7 @@
}
}
} finally {
- if (isBlock) {
+ if (isBlocking) {
end();
}
}
@@ -254,24 +254,25 @@
pollFd.userData = null;
int ops = key.interestOpsNoCheck();
- int selectedOp = 0;
+ int selectedOps = 0;
if ((pollFd.revents & POLLIN) != 0) {
- selectedOp = ops & (OP_ACCEPT | OP_READ);
- } else if ((pollFd.revents & POLLOUT) != 0) {
+ selectedOps |= ops & (OP_ACCEPT | OP_READ);
+ }
+ if ((pollFd.revents & POLLOUT) != 0) {
if (key.isConnected()) {
- selectedOp = ops & OP_WRITE;
+ selectedOps |= ops & OP_WRITE;
} else {
- selectedOp = ops & OP_CONNECT;
+ selectedOps |= ops & OP_CONNECT;
}
}
- if (selectedOp != 0) {
+ if (selectedOps != 0) {
boolean wasSelected = mutableSelectedKeys.contains(key);
- if (wasSelected && key.readyOps() != selectedOp) {
- key.setReadyOps(key.readyOps() | selectedOp);
+ if (wasSelected && key.readyOps() != selectedOps) {
+ key.setReadyOps(key.readyOps() | selectedOps);
++readyKeyCount;
} else if (!wasSelected) {
- key.setReadyOps(selectedOp);
+ key.setReadyOps(selectedOps);
mutableSelectedKeys.add(key);
++readyKeyCount;
}
diff --git a/luni/src/main/java/java/nio/ServerSocketChannelImpl.java b/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
index 5331158..3fb61a3 100644
--- a/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/ServerSocketChannelImpl.java
@@ -31,7 +31,9 @@
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
+import libcore.io.ErrnoException;
import libcore.io.IoUtils;
+import static libcore.io.OsConstants.*;
/**
* The default ServerSocketChannel.
@@ -65,21 +67,17 @@
// Create an empty socket channel. This will be populated by ServerSocketAdapter.accept.
SocketChannelImpl result = new SocketChannelImpl(provider(), false);
- boolean connected = false;
try {
begin();
synchronized (acceptLock) {
- synchronized (blockingLock()) {
- do {
- try {
- socket.implAccept(result);
- // select successfully, break out immediately.
- break;
- } catch (SocketTimeoutException e) {
- // continue to accept if the channel is in blocking mode.
- // TODO: does this make sense? why does blocking imply no timeouts?
- }
- } while (isBlocking());
+ try {
+ socket.implAccept(result);
+ } catch (SocketTimeoutException e) {
+ if (shouldThrowSocketTimeoutExceptionFromAccept(e)) {
+ throw e;
+ }
+ // Otherwise, this is a non-blocking socket and there's nothing ready, so we'll
+ // fall through and return null.
}
}
} finally {
@@ -88,10 +86,21 @@
return result.socket().isConnected() ? result : null;
}
- @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
- synchronized (blockingLock()) {
- IoUtils.setBlocking(impl.getFD$(), blocking);
+ private boolean shouldThrowSocketTimeoutExceptionFromAccept(SocketTimeoutException e) {
+ if (isBlocking()) {
+ return true;
}
+ Throwable cause = e.getCause();
+ if (cause instanceof ErrnoException) {
+ if (((ErrnoException) cause).errno == EAGAIN) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override protected void implConfigureBlocking(boolean blocking) throws IOException {
+ IoUtils.setBlocking(impl.getFD$(), blocking);
}
synchronized protected void implCloseSelectableChannel() throws IOException {
diff --git a/luni/src/main/java/java/nio/SocketChannelImpl.java b/luni/src/main/java/java/nio/SocketChannelImpl.java
index 233daf0..714005f 100644
--- a/luni/src/main/java/java/nio/SocketChannelImpl.java
+++ b/luni/src/main/java/java/nio/SocketChannelImpl.java
@@ -177,7 +177,7 @@
finished = IoBridge.connect(fd, normalAddr, port);
isBound = finished;
} catch (IOException e) {
- if (e instanceof ConnectException && !isBlocking()) {
+ if (isEINPROGRESS(e)) {
status = SOCKET_STATUS_PENDING;
} else {
if (isOpen()) {
@@ -209,6 +209,19 @@
return finished;
}
+ private boolean isEINPROGRESS(IOException e) {
+ if (isBlocking()) {
+ return false;
+ }
+ if (e instanceof ConnectException) {
+ Throwable cause = e.getCause();
+ if (cause instanceof ErrnoException) {
+ return ((ErrnoException) cause).errno == EINPROGRESS;
+ }
+ }
+ return false;
+ }
+
private void initLocalAddressAndPort() {
SocketAddress sa;
try {
@@ -456,9 +469,7 @@
}
@Override protected void implConfigureBlocking(boolean blocking) throws IOException {
- synchronized (blockingLock()) {
- IoUtils.setBlocking(fd, blocking);
- }
+ IoUtils.setBlocking(fd, blocking);
}
/*
@@ -658,12 +669,12 @@
}
@Override
- public int read(byte[] buffer, int offset, int byteCount) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
if (!channel.isBlocking()) {
throw new IllegalBlockingModeException();
}
- ByteBuffer buf = ByteBuffer.wrap(buffer, offset, byteCount);
+ ByteBuffer buf = ByteBuffer.wrap(buffer, byteOffset, byteCount);
return channel.read(buf);
}
}
diff --git a/luni/src/main/java/java/nio/channels/Channels.java b/luni/src/main/java/java/nio/channels/Channels.java
index b59eeac..e354743 100644
--- a/luni/src/main/java/java/nio/channels/Channels.java
+++ b/luni/src/main/java/java/nio/channels/Channels.java
@@ -216,8 +216,8 @@
return Streams.readSingleByte(this);
}
- @Override public synchronized int read(byte[] target, int offset, int length) throws IOException {
- ByteBuffer buffer = ByteBuffer.wrap(target, offset, length);
+ @Override public synchronized int read(byte[] target, int byteOffset, int byteCount) throws IOException {
+ ByteBuffer buffer = ByteBuffer.wrap(target, byteOffset, byteCount);
checkBlocking(channel);
return channel.read(buffer);
}
diff --git a/luni/src/main/java/java/nio/channels/FileLock.java b/luni/src/main/java/java/nio/channels/FileLock.java
index 4cdcc27..360f826 100644
--- a/luni/src/main/java/java/nio/channels/FileLock.java
+++ b/luni/src/main/java/java/nio/channels/FileLock.java
@@ -68,7 +68,7 @@
* Further care should be exercised when locking files maintained on network
* file systems, since they often have further limitations.
*/
-public abstract class FileLock {
+public abstract class FileLock implements AutoCloseable {
// The underlying file channel.
private final FileChannel channel;
@@ -185,10 +185,16 @@
public abstract void release() throws IOException;
/**
- * Returns a string that shows the details of the lock suitable for display
- * to an end user.
+ * Calls {@link #release} for {@code AutoCloseable}.
*
- * @return the display string.
+ * @since 1.7
+ */
+ public final void close() throws IOException {
+ release();
+ }
+
+ /**
+ * Returns a string that shows the details of the lock suitable for debugging.
*/
@Override
public final String toString() {
diff --git a/luni/src/main/java/java/nio/channels/Selector.java b/luni/src/main/java/java/nio/channels/Selector.java
index 1aac14b..6d9b063 100644
--- a/luni/src/main/java/java/nio/channels/Selector.java
+++ b/luni/src/main/java/java/nio/channels/Selector.java
@@ -16,6 +16,7 @@
package java.nio.channels;
+import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.spi.SelectorProvider;
import java.util.Set;
@@ -33,7 +34,7 @@
* selector are checked to see whether they are ready for operation according to
* their {@link SelectionKey interest set}.
*/
-public abstract class Selector {
+public abstract class Selector implements Closeable {
/**
* Returns a selector returned by {@link SelectorProvider#provider}'s
diff --git a/luni/src/main/java/java/nio/charset/Charset.java b/luni/src/main/java/java/nio/charset/Charset.java
index 400aa8b..02cd42f 100644
--- a/luni/src/main/java/java/nio/charset/Charset.java
+++ b/luni/src/main/java/java/nio/charset/Charset.java
@@ -371,9 +371,7 @@
public abstract CharsetDecoder newDecoder();
/**
- * Gets the canonical name of this charset.
- *
- * @return this charset's name in canonical form.
+ * Returns the canonical name of this charset.
*/
public final String name() {
return this.canonicalName;
diff --git a/luni/src/main/java/java/nio/charset/CharsetDecoder.java b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
index 1559db4..7aa546c 100644
--- a/luni/src/main/java/java/nio/charset/CharsetDecoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetDecoder.java
@@ -303,12 +303,8 @@
* method threw an <code>BufferUnderflowException</code> or
* <code>BufferOverflowException</code>.
*/
- public final CoderResult decode(ByteBuffer in, CharBuffer out,
- boolean endOfInput) {
- /*
- * status check
- */
- if ((status == FLUSH) || (!endOfInput && status == END)) {
+ public final CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput) {
+ if (status == FLUSH || (!endOfInput && status == END)) {
throw new IllegalStateException();
}
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoder.java b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
index 8f02f96..c2d74a1 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoder.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoder.java
@@ -163,65 +163,27 @@
}
/**
- * Checks if the given character can be encoded by this encoder.
- * <p>
- * Note that this method can change the internal status of this encoder, so
+ * 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
* it should not be called when another encoding process is ongoing,
* otherwise it will throw an <code>IllegalStateException</code>.
- * <p>
- * This method can be overridden for performance improvement.
*
- * @param c
- * the given encoder.
- * @return true if given character can be encoded by this encoder.
- * @throws IllegalStateException
- * if another encode process is ongoing so that the current
- * internal status is neither RESET or FLUSH.
+ * @throws IllegalStateException if another encode process is ongoing.
*/
public boolean canEncode(char c) {
- return implCanEncode(CharBuffer.wrap(new char[] { c }));
- }
-
- // implementation of canEncode
- private boolean implCanEncode(CharBuffer cb) {
- if (status == FLUSH || status == INIT) {
- status = READY;
- }
- if (status != READY) {
- throw new IllegalStateException("encoding already in progress");
- }
- CodingErrorAction malformBak = malformedInputAction;
- CodingErrorAction unmapBak = unmappableCharacterAction;
- onMalformedInput(CodingErrorAction.REPORT);
- onUnmappableCharacter(CodingErrorAction.REPORT);
- boolean result = true;
- try {
- this.encode(cb);
- } catch (CharacterCodingException e) {
- result = false;
- }
- onMalformedInput(malformBak);
- onUnmappableCharacter(unmapBak);
- reset();
- return result;
+ return canEncode(CharBuffer.wrap(new char[] { c }));
}
/**
- * Checks if a given <code>CharSequence</code> can be encoded by this
+ * Tests whether the given <code>CharSequence</code> can be encoded by this
* encoder.
*
- * Note that this method can change the internal status of this encoder, so
+ * <p>Note that this method may change the internal status of this encoder, so
* it should not be called when another encode process is ongoing, otherwise
* it will throw an <code>IllegalStateException</code>.
*
- * This method can be overridden for performance improvement.
- *
- * @param sequence
- * the given <code>CharSequence</code>.
- * @return true if the given <code>CharSequence</code> can be encoded by
- * this encoder.
- * @throws IllegalStateException
- * if current internal status is neither RESET or FLUSH.
+ * @throws IllegalStateException if another encode process is ongoing.
*/
public boolean canEncode(CharSequence sequence) {
CharBuffer cb;
@@ -230,7 +192,27 @@
} else {
cb = CharBuffer.wrap(sequence);
}
- return implCanEncode(cb);
+
+ if (status == FLUSH || status == INIT) {
+ status = READY;
+ }
+ if (status != READY) {
+ throw new IllegalStateException();
+ }
+ CodingErrorAction originalMalformedInputAction = malformedInputAction;
+ CodingErrorAction originalUnmappableCharacterAction = unmappableCharacterAction;
+ onMalformedInput(CodingErrorAction.REPORT);
+ onUnmappableCharacter(CodingErrorAction.REPORT);
+ try {
+ this.encode(cb);
+ return true;
+ } catch (CharacterCodingException e) {
+ return false;
+ } finally {
+ onMalformedInput(originalMalformedInputAction);
+ onUnmappableCharacter(originalUnmappableCharacterAction);
+ reset();
+ }
}
/**
@@ -272,54 +254,47 @@
* if other exception happened during the encode operation.
*/
public final ByteBuffer encode(CharBuffer in) throws CharacterCodingException {
- if (in.remaining() == 0) {
- return ByteBuffer.allocate(0);
- }
- reset();
int length = (int) (in.remaining() * averageBytesPerChar);
- ByteBuffer output = ByteBuffer.allocate(length);
- CoderResult result = null;
- while (true) {
- result = encode(in, output, false);
- if (result==CoderResult.UNDERFLOW) {
- break;
- } else if (result==CoderResult.OVERFLOW) {
- output = allocateMore(output);
- continue;
- }
- checkCoderResult(result);
+ ByteBuffer out = ByteBuffer.allocate(length);
+ if (in.hasRemaining() == false) {
+ return out;
}
- result = encode(in, output, true);
- checkCoderResult(result);
- while (true) {
- result = flush(output);
- if (result==CoderResult.UNDERFLOW) {
- output.flip();
+ reset();
+
+ while (in.hasRemaining()) {
+ CoderResult result = encode(in, out, true);
+ if (result == CoderResult.UNDERFLOW) {
break;
- } else if (result==CoderResult.OVERFLOW) {
- output = allocateMore(output);
+ } else if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
continue;
+ } else {
+ checkCoderResult(result);
}
- checkCoderResult(result);
- output.flip();
- if (result.isMalformed()) {
- throw new MalformedInputException(result.length());
- } else if (result.isUnmappable()) {
- throw new UnmappableCharacterException(result.length());
+
+ result = flush(out);
+ if (result == CoderResult.UNDERFLOW) {
+ break;
+ } else if (result == CoderResult.OVERFLOW) {
+ out = allocateMore(out);
+ continue;
+ } else {
+ checkCoderResult(result);
}
- break;
}
+
+ out.flip();
status = READY;
finished = true;
- return output;
+ return out;
}
/*
* checks the result whether it needs to throw CharacterCodingException.
*/
private void checkCoderResult(CoderResult result) throws CharacterCodingException {
- if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed() ) {
+ if (malformedInputAction == CodingErrorAction.REPORT && result.isMalformed()) {
throw new MalformedInputException(result.length());
} else if (unmappableCharacterAction == CodingErrorAction.REPORT && result.isUnmappable()) {
throw new UnmappableCharacterException(result.length());
@@ -405,12 +380,14 @@
if (status == READY && finished && !endOfInput) {
throw new IllegalStateException();
}
- if ((status == FLUSH) || (!endOfInput && status == END)) {
+ if (status == FLUSH || (!endOfInput && status == END)) {
throw new IllegalStateException();
}
- CoderResult result;
+ status = endOfInput ? END : ONGOING;
+
while (true) {
+ CoderResult result;
try {
result = encodeLoop(in, out);
} catch (BufferOverflowException e) {
@@ -418,37 +395,25 @@
} catch (BufferUnderflowException e) {
throw new CoderMalfunctionError(e);
}
- if (result==CoderResult.UNDERFLOW) {
- status = endOfInput ? END : ONGOING;
- if (endOfInput) {
- int remaining = in.remaining();
- if (remaining > 0) {
- result = CoderResult.malformedForLength(remaining);
- } else {
- return result;
- }
+ if (result == CoderResult.UNDERFLOW) {
+ if (endOfInput && in.hasRemaining()) {
+ result = CoderResult.malformedForLength(in.remaining());
} else {
return result;
}
- } else if (result==CoderResult.OVERFLOW) {
- status = endOfInput ? END : ONGOING;
+ } else if (result == CoderResult.OVERFLOW) {
return result;
}
- CodingErrorAction action = malformedInputAction;
- if (result.isUnmappable()) {
- action = unmappableCharacterAction;
+ CodingErrorAction action =
+ result.isUnmappable() ? unmappableCharacterAction : malformedInputAction;
+ if (action == CodingErrorAction.REPORT) {
+ return result;
}
- // If the action is IGNORE or REPLACE, we should continue
- // encoding.
if (action == CodingErrorAction.REPLACE) {
if (out.remaining() < replacementBytes.length) {
return CoderResult.OVERFLOW;
}
out.put(replacementBytes);
- } else {
- if (action != CodingErrorAction.IGNORE) {
- return result;
- }
}
in.position(in.position() + result.length());
}
@@ -467,9 +432,9 @@
* {@link #encode(CharBuffer, ByteBuffer, boolean) encode}. When an
* exception is encountered in the encoding operation, most implementations
* of this method will return a relevant result object to the
- * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and some
- * performance optimized implementation may handle the exception and
- * implement the error action itself.
+ * {@link #encode(CharBuffer, ByteBuffer, boolean) encode} method, and
+ * subclasses may handle the exception and
+ * implement the error action themselves.
* <p>
* The buffers are scanned from their current positions, and their positions
* will be modified accordingly, while their marks and limits will be
@@ -588,18 +553,9 @@
}
/**
- * Checks if the given argument is legal as this encoder's replacement byte
- * array.
- *
- * The given byte array is legal if and only if it can be decode into
- * sixteen bits Unicode characters.
- *
- * This method can be overridden for performance improvement.
- *
- * @param replacement
- * the given byte array to be checked.
- * @return true if the the given argument is legal as this encoder's
- * replacement byte array.
+ * Tests whether the given argument is legal as this encoder's replacement byte
+ * array. The given byte array is legal if and only if it can be decoded into
+ * characters.
*/
public boolean isLegalReplacement(byte[] replacement) {
if (decoder == null) {
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index 76807b0..4bc4354 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -184,14 +184,6 @@
}
}
- public boolean canEncode(char c) {
- return canEncode((int) c);
- }
-
- public boolean canEncode(int codePoint) {
- return NativeConverter.canEncode(converterHandle, codePoint);
- }
-
@Override protected void finalize() throws Throwable {
try {
NativeConverter.closeConverter(converterHandle);
diff --git a/luni/src/main/java/java/nio/charset/Charsets.java b/luni/src/main/java/java/nio/charset/Charsets.java
index 826b12a..3dede7a 100644
--- a/luni/src/main/java/java/nio/charset/Charsets.java
+++ b/luni/src/main/java/java/nio/charset/Charsets.java
@@ -17,31 +17,12 @@
package java.nio.charset;
/**
- * Provides convenient access to the most important built-in charsets. Saves a hash lookup and
- * unnecessary handling of UnsupportedEncodingException at call sites, compared to using the
- * charset's name.
- *
- * Also various special-case charset conversions (for performance).
+ * Various special-case charset conversions (for performance).
*
* @hide internal use only
*/
public final class Charsets {
/**
- * A cheap and type-safe constant for the ISO-8859-1 Charset.
- */
- public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
-
- /**
- * A cheap and type-safe constant for the US-ASCII Charset.
- */
- public static final Charset US_ASCII = Charset.forName("US-ASCII");
-
- /**
- * A cheap and type-safe constant for the UTF-8 Charset.
- */
- public static final Charset UTF_8 = Charset.forName("UTF-8");
-
- /**
* Returns a new byte array containing the bytes corresponding to the given characters,
* encoded in US-ASCII. Unrepresentable characters are replaced by (byte) '?'.
*/
diff --git a/luni/src/main/java/java/nio/charset/CoderResult.java b/luni/src/main/java/java/nio/charset/CoderResult.java
index 3cc2673..6c45e26 100644
--- a/luni/src/main/java/java/nio/charset/CoderResult.java
+++ b/luni/src/main/java/java/nio/charset/CoderResult.java
@@ -154,8 +154,6 @@
/**
* Returns true if this result is an underflow condition.
- *
- * @return true if an underflow, otherwise false.
*/
public boolean isUnderflow() {
return this.type == TYPE_UNDERFLOW;
@@ -164,19 +162,13 @@
/**
* Returns true if this result represents a malformed-input error or an
* unmappable-character error.
- *
- * @return true if this is a malformed-input error or an
- * unmappable-character error, otherwise false.
*/
public boolean isError() {
- return this.type == TYPE_MALFORMED_INPUT
- || this.type == TYPE_UNMAPPABLE_CHAR;
+ return this.type == TYPE_MALFORMED_INPUT || this.type == TYPE_UNMAPPABLE_CHAR;
}
/**
* Returns true if this result represents a malformed-input error.
- *
- * @return true if this is a malformed-input error, otherwise false.
*/
public boolean isMalformed() {
return this.type == TYPE_MALFORMED_INPUT;
@@ -184,8 +176,6 @@
/**
* Returns true if this result is an overflow condition.
- *
- * @return true if this is an overflow, otherwise false.
*/
public boolean isOverflow() {
return this.type == TYPE_OVERFLOW;
@@ -193,18 +183,15 @@
/**
* Returns true if this result represents an unmappable-character error.
- *
- * @return true if this is an unmappable-character error, otherwise false.
*/
public boolean isUnmappable() {
return this.type == TYPE_UNMAPPABLE_CHAR;
}
/**
- * Gets the length of the erroneous input. The length is only meaningful to
+ * Returns the length of the erroneous input. The length is only meaningful for
* a malformed-input error or an unmappable character error.
*
- * @return the length, as an integer, of this object's erroneous input.
* @throws UnsupportedOperationException
* if this result is an overflow or underflow.
*/
diff --git a/luni/src/main/java/java/nio/charset/StandardCharsets.java b/luni/src/main/java/java/nio/charset/StandardCharsets.java
new file mode 100644
index 0000000..66fa9f6
--- /dev/null
+++ b/luni/src/main/java/java/nio/charset/StandardCharsets.java
@@ -0,0 +1,56 @@
+/*
+ * 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.nio.charset;
+
+/**
+ * Convenient access to the most important built-in charsets.
+ * @since 1.7
+ */
+public final class StandardCharsets {
+ private StandardCharsets() {
+ }
+
+ /**
+ * The ISO-8859-1 charset.
+ */
+ public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
+
+ /**
+ * The US-ASCII charset.
+ */
+ public static final Charset US_ASCII = Charset.forName("US-ASCII");
+
+ /**
+ * The UTF-8 charset.
+ */
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+ /**
+ * The UTF-16 charset.
+ */
+ public static final Charset UTF_16 = Charset.forName("UTF-16");
+
+ /**
+ * The UTF-16BE (big-endian) charset.
+ */
+ public static final Charset UTF_16BE = Charset.forName("UTF-16BE");
+
+ /**
+ * The UTF-16LE (little-endian) charset.
+ */
+ public static final Charset UTF_16LE = Charset.forName("UTF-16LE");
+}
diff --git a/luni/src/main/java/java/security/Certificate.java b/luni/src/main/java/java/security/Certificate.java
index afec0d3..1d410a1 100644
--- a/luni/src/main/java/java/security/Certificate.java
+++ b/luni/src/main/java/java/security/Certificate.java
@@ -27,7 +27,7 @@
* validity of itself. It's in the responsibility of the application to verify
* the validity of its certificates.
*
- * @deprecated Replaced by behavior in {@link java.security.cert}
+ * @deprecated Use {@link java.security.cert.Certificate} instead.
* @see java.security.cert.Certificate
*/
@Deprecated
diff --git a/luni/src/main/java/java/security/DigestInputStream.java b/luni/src/main/java/java/security/DigestInputStream.java
index e7d97ca..655c11f 100644
--- a/luni/src/main/java/java/security/DigestInputStream.java
+++ b/luni/src/main/java/java/security/DigestInputStream.java
@@ -96,33 +96,26 @@
}
/**
- * Reads {@code len} bytes into the specified {@code byte[]}, starting from
- * the specified offset. Updates the digest if this function is
+ * Reads up to {@code byteCount} bytes into {@code buffer}, starting at
+ * {@code byteOffset}. Updates the digest if this function is
* {@link #on(boolean)}.
- * <p>
- * This operation is blocking.
*
- * @param b
- * the byte array in which to store the bytes
- * @param off
- * the initial position in {@code b} to store the bytes read from
- * this stream
- * @param len
- * the maximum number of bytes to store in {@code b}
- * @return the number of bytes actually read or -1 if the end of the
- * filtered stream has been reached while reading
+ * <p>This operation is blocking.
+ *
+ * <p>Returns the number of bytes actually read or -1 if the end of the
+ * filtered stream has been reached while reading.
+ *
* @throws IOException
* if reading the source stream causes an {@code IOException}
*/
@Override
- public int read(byte[] b, int off, int len) throws IOException {
- // read next up to len bytes
- int bytesRead = in.read(b, off, len);
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ int bytesRead = in.read(buffer, byteOffset, byteCount);
// update digest only if
// - digest functionality is on
// - eos has not been reached
if (isOn && (bytesRead != -1)) {
- digest.update(b, off, bytesRead);
+ digest.update(buffer, byteOffset, bytesRead);
}
// return number of bytes read
return bytesRead;
diff --git a/luni/src/main/java/java/security/Identity.java b/luni/src/main/java/java/security/Identity.java
index 6e5b8a3..f0eef5d 100644
--- a/luni/src/main/java/java/security/Identity.java
+++ b/luni/src/main/java/java/security/Identity.java
@@ -25,9 +25,8 @@
/**
* {@code Identity} represents an identity like a person or a company.
*
- * @deprecated The functionality of this class has been replace by
- * {@link Principal}, {@link KeyStore} and the {@code
- * java.security.cert} package.
+ * @deprecated Use {@link Principal}, {@link KeyStore} and the {@code java.security.cert} package
+ * instead.
*/
@Deprecated
public abstract class Identity implements Principal, Serializable {
diff --git a/luni/src/main/java/java/security/IdentityScope.java b/luni/src/main/java/java/security/IdentityScope.java
index 1e344fd..ee17b58 100644
--- a/luni/src/main/java/java/security/IdentityScope.java
+++ b/luni/src/main/java/java/security/IdentityScope.java
@@ -23,9 +23,8 @@
/**
* {@code IdentityScope} represents a scope for {@link Identity} objects.
*
- * @deprecated The functionality of this class has been replace by
- * {@link Principal}, {@link KeyStore} and the {@code
- * java.security.cert} package.
+ * @deprecated Use {@link Principal}, {@link KeyStore} and the {@code java.security.cert} package
+ * instead.
*/
@Deprecated
public abstract class IdentityScope extends Identity {
diff --git a/luni/src/main/java/java/security/Security.java b/luni/src/main/java/java/security/Security.java
index b5bd02a..0b6961b 100644
--- a/luni/src/main/java/java/security/Security.java
+++ b/luni/src/main/java/java/security/Security.java
@@ -17,7 +17,6 @@
package java.security;
-
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.Enumeration;
@@ -72,11 +71,11 @@
// Register default providers
private static void registerDefaultProviders() {
- secprops.put("security.provider.1", "org.apache.harmony.xnet.provider.jsse.OpenSSLProvider");
+ secprops.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
secprops.put("security.provider.2", "org.apache.harmony.security.provider.cert.DRLCertFactory");
- secprops.put("security.provider.3", "org.bouncycastle.jce.provider.BouncyCastleProvider");
+ secprops.put("security.provider.3", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
secprops.put("security.provider.4", "org.apache.harmony.security.provider.crypto.CryptoProvider");
- secprops.put("security.provider.5", "org.apache.harmony.xnet.provider.jsse.JSSEProvider");
+ secprops.put("security.provider.5", "com.android.org.conscrypt.JSSEProvider");
}
/**
@@ -87,8 +86,7 @@
* @param propName
* the name of the property.
* @return value of the property.
- * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory}
- * instead.
+ * @deprecated Use {@link AlgorithmParameters} and {@link KeyFactory} instead.
*/
@Deprecated
public static String getAlgorithmProperty(String algName, String propName) {
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index b2bd122..0372c33 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -523,7 +523,7 @@
* @throws InvalidParameterException
* if the parameter is invalid, already set or is not allowed to
* be changed.
- * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)}
+ * @deprecated Use {@link #setParameter(AlgorithmParameterSpec)} instead.
*/
@Deprecated
public final void setParameter(String param, Object value)
@@ -565,7 +565,7 @@
* null}.
* @throws InvalidParameterException
* if {@code param} is not a valid parameter for this {@code
- * Signature} or an other error occures.
+ * Signature} or an other error occurs.
* @deprecated There is no generally accepted parameter naming convention.
*/
@Deprecated
diff --git a/luni/src/main/java/java/security/Signer.java b/luni/src/main/java/java/security/Signer.java
index b892090..8f8ef06 100644
--- a/luni/src/main/java/java/security/Signer.java
+++ b/luni/src/main/java/java/security/Signer.java
@@ -21,9 +21,8 @@
* {@link Signer} represents an identity (individual or corporation) that owns a
* private key and the corresponding public key.
*
- * @deprecated Replaced by behavior in {@link java.security.cert
- * java.security.cert} package and {@link java.security.Principal
- * Principal}
+ * @deprecated Use the {@link java.security.cert java.security.cert} package
+ * and {@link java.security.Principal} instead.
*/
@Deprecated
public abstract class Signer extends Identity {
diff --git a/luni/src/main/java/java/security/security.properties b/luni/src/main/java/java/security/security.properties
index b124271..dd5830d 100644
--- a/luni/src/main/java/java/security/security.properties
+++ b/luni/src/main/java/java/security/security.properties
@@ -19,14 +19,14 @@
# See also: J2SE doc. "How to Implement a Provider for the JavaTM Cryptography Architecture"
#
# Android's provider of OpenSSL backed implementations
-security.provider.1=org.apache.harmony.xnet.provider.jsse.OpenSSLProvider
+security.provider.1=com.android.org.conscrypt.OpenSSLProvider
# Favor Harmony's CertificateFactory.X509 over BouncyCastle's
security.provider.2=org.apache.harmony.security.provider.cert.DRLCertFactory
# Android's stripped down BouncyCastle provider
security.provider.3=com.android.org.bouncycastle.jce.provider.BouncyCastleProvider
# Remaining Harmony providers
security.provider.4=org.apache.harmony.security.provider.crypto.CryptoProvider
-security.provider.5=org.apache.harmony.xnet.provider.jsse.JSSEProvider
+security.provider.5=com.android.org.conscrypt.JSSEProvider
@@ -40,11 +40,11 @@
# javax/net/ssl/SSLServerSocketFactory.html#getDefault()
# For regular SSLSockets, we have two implementations:
-ssl.SocketFactory.provider=org.apache.harmony.xnet.provider.jsse.OpenSSLSocketFactoryImpl
-#ssl.SocketFactory.provider=org.apache.harmony.xnet.provider.jsse.SSLSocketFactoryImpl
+ssl.SocketFactory.provider=com.android.org.conscrypt.OpenSSLSocketFactoryImpl
+#ssl.SocketFactory.provider=com.android.org.conscrypt.SSLSocketFactoryImpl
# For SSLServerSockets, there's only the new, OpenSSL-based implementation:
-ssl.ServerSocketFactory.provider=org.apache.harmony.xnet.provider.jsse.OpenSSLServerSocketFactoryImpl
+ssl.ServerSocketFactory.provider=com.android.org.conscrypt.OpenSSLSocketFactoryImpl
# Default KeyStore type.
# See specification for java/security/KeyStore.html#getDefaultType()
diff --git a/luni/src/main/java/java/sql/CallableStatement.java b/luni/src/main/java/java/sql/CallableStatement.java
index 5bd9c52..162841d 100644
--- a/luni/src/main/java/java/sql/CallableStatement.java
+++ b/luni/src/main/java/java/sql/CallableStatement.java
@@ -111,8 +111,7 @@
* the parameter in question is an SQL {@code NULL}.
* @throws SQLException
* if a database error occurs.
- * @deprecated Use {@link #getBigDecimal(int)} or
- * {@link #getBigDecimal(String)}
+ * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
*/
@Deprecated
public BigDecimal getBigDecimal(int parameterIndex, int scale)
diff --git a/luni/src/main/java/java/sql/Date.java b/luni/src/main/java/java/sql/Date.java
index 34ca5bd..4aac326 100644
--- a/luni/src/main/java/java/sql/Date.java
+++ b/luni/src/main/java/java/sql/Date.java
@@ -41,7 +41,7 @@
* Constructs a {@code Date} object corresponding to the supplied year,
* month and day.
*
- * @deprecated Use the constructor {@link #Date(long)}.
+ * @deprecated Use the constructor {@link #Date(long)} instead.
* @param theYear
* the year, specified as the year minus 1900. Must be in the
* range {@code [0,8099]}.
diff --git a/luni/src/main/java/java/sql/DriverManager.java b/luni/src/main/java/java/sql/DriverManager.java
index 550ccae..58fc068 100644
--- a/luni/src/main/java/java/sql/DriverManager.java
+++ b/luni/src/main/java/java/sql/DriverManager.java
@@ -281,7 +281,7 @@
* Gets the log {@code PrintStream} used by the {@code DriverManager} and
* all the JDBC Drivers.
*
- * @deprecated use {@link #getLogWriter()} instead.
+ * @deprecated Use {@link #getLogWriter()} instead.
* @return the {@code PrintStream} used for logging activities.
*/
@Deprecated
diff --git a/luni/src/main/java/java/sql/ResultSet.java b/luni/src/main/java/java/sql/ResultSet.java
index 64ecb59..12b681a 100644
--- a/luni/src/main/java/java/sql/ResultSet.java
+++ b/luni/src/main/java/java/sql/ResultSet.java
@@ -298,8 +298,7 @@
* Gets the value of a column specified by column index as a {@code
* java.math.BigDecimal}.
*
- * @deprecated use {@link #getBigDecimal(int)} or
- * {@link #getBigDecimal(String)}
+ * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
* @param columnIndex
* the index of the column to read.
* @param scale
@@ -328,8 +327,7 @@
* Gets the value of a column specified by column name, as a {@code
* java.math.BigDecimal}.
*
- * @deprecated use {@link #getBigDecimal(int)} or
- * {@link #getBigDecimal(String)}
+ * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)} instead.
* @param columnName
* the name of the column to read.
* @param scale
@@ -1050,7 +1048,7 @@
* Gets the value of the column as an {@code InputStream} of unicode
* characters.
*
- * @deprecated Use {@link #getCharacterStream}.
+ * @deprecated Use {@link #getCharacterStream} instead.
* @param columnIndex
* the index of the column to read.
* @return an {@code InputStream} holding the value of the column. {@code
@@ -1065,7 +1063,7 @@
* Gets the value of the column as an {@code InputStream} of Unicode
* characters.
*
- * @deprecated Use {@link #getCharacterStream}
+ * @deprecated Use {@link #getCharacterStream} instead.
* @param columnName
* the name of the column to read.
* @return an {@code InputStream} holding the value of the column. {@code
diff --git a/luni/src/main/java/java/sql/Time.java b/luni/src/main/java/java/sql/Time.java
index 913379c..c6e2f20 100644
--- a/luni/src/main/java/java/sql/Time.java
+++ b/luni/src/main/java/java/sql/Time.java
@@ -39,7 +39,7 @@
* <p>
* The result is undefined if any argument is out of bounds.
*
- * @deprecated Use the constructor {@link #Time(long)}.
+ * @deprecated Use the constructor {@link #Time(long)} instead.
* @param theHour
* a value in the range {@code [0,23]}.
* @param theMinute
@@ -67,7 +67,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a {@code Date} component.
+ * {@code Time} object does not have a date component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
@@ -81,7 +81,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a <i>Day</i> component.
+ * {@code Time} object does not have a day component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
@@ -95,7 +95,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a <i>Month</i> component.
+ * {@code Time} object does not have a month component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
@@ -109,7 +109,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a <i>Year</i> component.
+ * {@code Time} object does not have a year component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
@@ -123,7 +123,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a {@code Date} component.
+ * {@code Time} object does not have a date component.
* @throws IllegalArgumentException
* if this method is called.
*/
@@ -136,7 +136,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a <i>Month</i> component.
+ * {@code Time} object does not have a month component.
* @throws IllegalArgumentException
* if this method is called.
*/
@@ -149,7 +149,7 @@
/**
* @deprecated This method is deprecated and must not be used. An SQL
- * {@code Time} object does not have a <i>Year</i> component.
+ * {@code Time} object does not have a year component.
* @throws IllegalArgumentException
* if this method is called.
*/
diff --git a/luni/src/main/java/java/sql/Timestamp.java b/luni/src/main/java/java/sql/Timestamp.java
index 2e6d3d9..f35fa9b 100644
--- a/luni/src/main/java/java/sql/Timestamp.java
+++ b/luni/src/main/java/java/sql/Timestamp.java
@@ -57,7 +57,7 @@
* supplied values for <i>Year</i>, <i>Month</i>, <i>Date</i>, <i>Hour</i>,
* <i>Minutes</i>, <i>Seconds</i> and <i>Nanoseconds</i>.
*
- * @deprecated Use the constructor {@link #Timestamp(long)}.
+ * @deprecated Use the constructor {@link #Timestamp(long)} instead.
* @param theYear
* specified as the year minus 1900.
* @param theMonth
diff --git a/luni/src/main/java/java/text/SimpleDateFormat.java b/luni/src/main/java/java/text/SimpleDateFormat.java
index a3dc722..04287ae 100644
--- a/luni/src/main/java/java/text/SimpleDateFormat.java
+++ b/luni/src/main/java/java/text/SimpleDateFormat.java
@@ -86,7 +86,7 @@
* <tr> <td>{@code s}</td> <td>second in minute</td> <td>(Number)</td> <td>55</td> </tr>
* <tr> <td>{@code w}</td> <td>week in year</td> <td>(Number)</td> <td>27</td> </tr>
* <tr> <td>{@code y}</td> <td>year</td> <td>(Number)</td> <td>{@code yy}:10 {@code y}/{@code yyy}/{@code yyyy}:2010</td> </tr>
- * <tr> <td>{@code z}</td> <td>time zone</td> <td>(Timezone)</td> <td>{@code z}/{@code zz}/{@code zzz}:PST {@code zzzz}:Pacific Standard Time</td> </tr>
+ * <tr> <td>{@code z}</td> <td>time zone</td> <td>(Time Zone)</td> <td>{@code z}/{@code zz}/{@code zzz}:PST {@code zzzz}:Pacific Standard Time</td> </tr>
* <tr> <td>{@code '}</td> <td>escape for text</td> <td>(Delimiter)</td> <td>{@code 'Date='}:Date=</td> </tr>
* <tr> <td>{@code ''}</td> <td>single quote</td> <td>(Literal)</td> <td>{@code 'o''clock'}:o'clock</td> </tr>
* </table>
@@ -250,22 +250,6 @@
}
/**
- * Validates the format character.
- *
- * @param format
- * the format character
- *
- * @throws IllegalArgumentException
- * when the format character is invalid
- */
- private void validateFormat(char format) {
- int index = PATTERN_CHARS.indexOf(format);
- if (index == -1) {
- throw new IllegalArgumentException("Unknown pattern character '" + format + "'");
- }
- }
-
- /**
* Validates the pattern.
*
* @param template
@@ -285,7 +269,7 @@
next = (template.charAt(i));
if (next == '\'') {
if (count > 0) {
- validateFormat((char) last);
+ validatePatternCharacter((char) last);
count = 0;
}
if (last == next) {
@@ -302,21 +286,21 @@
count++;
} else {
if (count > 0) {
- validateFormat((char) last);
+ validatePatternCharacter((char) last);
}
last = next;
count = 1;
}
} else {
if (count > 0) {
- validateFormat((char) last);
+ validatePatternCharacter((char) last);
count = 0;
}
last = -1;
}
}
if (count > 0) {
- validateFormat((char) last);
+ validatePatternCharacter((char) last);
}
if (quote) {
@@ -324,6 +308,13 @@
}
}
+ private void validatePatternCharacter(char format) {
+ int index = PATTERN_CHARS.indexOf(format);
+ if (index == -1) {
+ throw new IllegalArgumentException("Unknown pattern character '" + format + "'");
+ }
+ }
+
/**
* Constructs a new {@code SimpleDateFormat} using the specified
* non-localized pattern and {@code DateFormatSymbols} and the {@code
diff --git a/luni/src/main/java/java/util/Arrays.java b/luni/src/main/java/java/util/Arrays.java
index c1b2727..2c84795 100644
--- a/luni/src/main/java/java/util/Arrays.java
+++ b/luni/src/main/java/java/util/Arrays.java
@@ -150,6 +150,7 @@
* the array.
* @return a {@code List} of the elements of the specified array.
*/
+ @SafeVarargs
public static <T> List<T> asList(T... array) {
return new ArrayList<T>(array);
}
diff --git a/luni/src/main/java/java/util/BitSet.java b/luni/src/main/java/java/util/BitSet.java
index 9dfe35e..736f272 100644
--- a/luni/src/main/java/java/util/BitSet.java
+++ b/luni/src/main/java/java/util/BitSet.java
@@ -611,7 +611,7 @@
* Returns the index of the first bit that is set on or before {@code index}, or -1 if
* no lower bits are set or {@code index == -1}.
* @throws IndexOutOfBoundsException if {@code index < -1}.
- * @hide 1.7
+ * @since 1.7
*/
public int previousSetBit(int index) {
if (index == -1) {
@@ -631,7 +631,7 @@
* Returns the index of the first bit that is clear on or before {@code index}, or -1 if
* no lower bits are clear or {@code index == -1}.
* @throws IndexOutOfBoundsException if {@code index < -1}.
- * @hide 1.7
+ * @since 1.7
*/
public int previousClearBit(int index) {
if (index == -1) {
@@ -669,7 +669,7 @@
* Equivalent to {@code BitSet.valueOf(LongBuffer.wrap(longs))}, but likely to be faster.
* This is likely to be the fastest way to create a {@code BitSet} because it's closest
* to the internal representation.
- * @hide 1.7
+ * @since 1.7
*/
public static BitSet valueOf(long[] longs) {
return new BitSet(longs.clone());
@@ -678,7 +678,7 @@
/**
* Returns a {@code BitSet} corresponding to {@code longBuffer}, interpreted as a little-endian
* sequence of bits. This method does not alter the {@code LongBuffer}.
- * @hide 1.7
+ * @since 1.7
*/
public static BitSet valueOf(LongBuffer longBuffer) {
// The bulk get would mutate LongBuffer (even if we reset position later), and it's not
@@ -693,7 +693,7 @@
/**
* Equivalent to {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}.
- * @hide 1.7
+ * @since 1.7
*/
public static BitSet valueOf(byte[] bytes) {
return BitSet.valueOf(ByteBuffer.wrap(bytes));
@@ -702,7 +702,7 @@
/**
* Returns a {@code BitSet} corresponding to {@code byteBuffer}, interpreted as a little-endian
* sequence of bits. This method does not alter the {@code ByteBuffer}.
- * @hide 1.7
+ * @since 1.7
*/
public static BitSet valueOf(ByteBuffer byteBuffer) {
byteBuffer = byteBuffer.slice().order(ByteOrder.LITTLE_ENDIAN);
@@ -721,7 +721,7 @@
* Returns a new {@code long[]} containing a little-endian representation of the bits of
* this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
* this {@code BitSet}.
- * @hide 1.7
+ * @since 1.7
*/
public long[] toLongArray() {
return Arrays.copyOf(bits, longCount);
@@ -731,7 +731,7 @@
* Returns a new {@code byte[]} containing a little-endian representation the bits of
* this {@code BitSet}, suitable for passing to {@code valueOf} to reconstruct
* this {@code BitSet}.
- * @hide 1.7
+ * @since 1.7
*/
public byte[] toByteArray() {
int bitCount = length();
diff --git a/luni/src/main/java/java/util/Collections.java b/luni/src/main/java/java/util/Collections.java
index 491642b..932dcc1 100644
--- a/luni/src/main/java/java/util/Collections.java
+++ b/luni/src/main/java/java/util/Collections.java
@@ -2435,7 +2435,7 @@
/**
* Returns an enumeration containing no elements.
- * @hide 1.7
+ * @since 1.7
*/
@SuppressWarnings("unchecked")
public static <T> Enumeration<T> emptyEnumeration() {
@@ -2444,7 +2444,7 @@
/**
* Returns an iterator containing no elements.
- * @hide 1.7
+ * @since 1.7
*/
@SuppressWarnings("unchecked")
public static <T> Iterator<T> emptyIterator() {
@@ -2453,7 +2453,7 @@
/**
* Returns a list iterator containing no elements.
- * @hide 1.7
+ * @since 1.7
*/
public static <T> ListIterator<T> emptyListIterator() {
return Collections.<T>emptyList().listIterator();
@@ -2584,6 +2584,7 @@
* if at least one of the elements can't be inserted into the
* collection.
*/
+ @SafeVarargs
public static <T> boolean addAll(Collection<? super T> c, T... a) {
boolean modified = false;
for (int i = 0; i < a.length; i++) {
diff --git a/luni/src/main/java/java/util/ConcurrentModificationException.java b/luni/src/main/java/java/util/ConcurrentModificationException.java
index 5e5126a..634011f 100644
--- a/luni/src/main/java/java/util/ConcurrentModificationException.java
+++ b/luni/src/main/java/java/util/ConcurrentModificationException.java
@@ -51,7 +51,6 @@
* Constructs a new {@code ConcurrentModificationException} with the given detail
* message and cause.
* @since 1.7
- * @hide 1.7
*/
public ConcurrentModificationException(String detailMessage, Throwable cause) {
super(detailMessage, cause);
@@ -60,7 +59,6 @@
/**
* Constructs a new {@code ConcurrentModificationException} with the given cause.
* @since 1.7
- * @hide 1.7
*/
public ConcurrentModificationException(Throwable cause) {
super(cause);
diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java
index ceda24e..b5b04a0 100644
--- a/luni/src/main/java/java/util/Currency.java
+++ b/luni/src/main/java/java/util/Currency.java
@@ -91,7 +91,6 @@
/**
* Returns a set of all known currencies.
* @since 1.7
- * @hide 1.7
*/
public static Set<Currency> getAvailableCurrencies() {
Set<Currency> result = new LinkedHashSet<Currency>();
@@ -113,7 +112,6 @@
* Equivalent to {@code getDisplayName(Locale.getDefault())}.
* See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
* @since 1.7
- * @hide 1.7
*/
public String getDisplayName() {
return getDisplayName(Locale.getDefault());
@@ -123,7 +121,6 @@
* Returns the localized name of this currency in the given {@code locale}.
* Returns the ISO 4217 currency code if no localized name is available.
* @since 1.7
- * @hide 1.7
*/
public String getDisplayName(Locale locale) {
return ICU.getCurrencyDisplayName(locale.toString(), currencyCode);
diff --git a/luni/src/main/java/java/util/Date.java b/luni/src/main/java/java/util/Date.java
index da9f296..b4de055 100644
--- a/luni/src/main/java/java/util/Date.java
+++ b/luni/src/main/java/java/util/Date.java
@@ -69,8 +69,7 @@
* @param day
* the day of the month, 1 - 31.
*
- * @deprecated use
- * {@link GregorianCalendar#GregorianCalendar(int, int, int)}
+ * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int)} instead.
*/
@Deprecated
public Date(int year, int month, int day) {
@@ -94,8 +93,7 @@
* @param minute
* the minute of the hour, 0 - 59.
*
- * @deprecated use
- * {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)}
+ * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int)} instead.
*/
@Deprecated
public Date(int year, int month, int day, int hour, int minute) {
@@ -121,8 +119,8 @@
* @param second
* the second of the minute, 0 - 59.
*
- * @deprecated use
- * {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
+ * @deprecated Use {@link GregorianCalendar#GregorianCalendar(int, int, int, int, int, int)}
+ * instead.
*/
@Deprecated
public Date(int year, int month, int day, int hour, int minute, int second) {
@@ -149,7 +147,7 @@
* @param string
* the String to parse.
*
- * @deprecated use {@link DateFormat}
+ * @deprecated Use {@link DateFormat} instead.
*/
@Deprecated
public Date(String string) {
@@ -238,7 +236,7 @@
*
* @return the day of the month.
*
- * @deprecated use {@code Calendar.get(Calendar.DATE)}
+ * @deprecated Use {@code Calendar.get(Calendar.DATE)} instead.
*/
@Deprecated
public int getDate() {
@@ -250,7 +248,7 @@
*
* @return the day of the week.
*
- * @deprecated use {@code Calendar.get(Calendar.DAY_OF_WEEK)}
+ * @deprecated Use {@code Calendar.get(Calendar.DAY_OF_WEEK)} instead.
*/
@Deprecated
public int getDay() {
@@ -262,7 +260,7 @@
*
* @return the hour of the day.
*
- * @deprecated use {@code Calendar.get(Calendar.HOUR_OF_DAY)}
+ * @deprecated Use {@code Calendar.get(Calendar.HOUR_OF_DAY)} instead.
*/
@Deprecated
public int getHours() {
@@ -274,7 +272,7 @@
*
* @return the minutes.
*
- * @deprecated use {@code Calendar.get(Calendar.MINUTE)}
+ * @deprecated Use {@code Calendar.get(Calendar.MINUTE)} instead.
*/
@Deprecated
public int getMinutes() {
@@ -286,7 +284,7 @@
*
* @return the month.
*
- * @deprecated use {@code Calendar.get(Calendar.MONTH)}
+ * @deprecated Use {@code Calendar.get(Calendar.MONTH)} instead.
*/
@Deprecated
public int getMonth() {
@@ -298,7 +296,7 @@
*
* @return the seconds.
*
- * @deprecated use {@code Calendar.get(Calendar.SECOND)}
+ * @deprecated Use {@code Calendar.get(Calendar.SECOND)} instead.
*/
@Deprecated
public int getSeconds() {
@@ -320,8 +318,7 @@
*
* @return the timezone offset in minutes of the default {@code TimeZone}.
*
- * @deprecated use
- * {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000}
+ * @deprecated Use {@code (Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000} instead.
*/
@Deprecated
public int getTimezoneOffset() {
@@ -334,7 +331,7 @@
*
* @return the year - 1900.
*
- * @deprecated use {@code Calendar.get(Calendar.YEAR) - 1900}
+ * @deprecated Use {@code Calendar.get(Calendar.YEAR) - 1900} instead.
*/
@Deprecated
public int getYear() {
@@ -376,7 +373,7 @@
* the String to parse.
* @return the millisecond value parsed from the String.
*
- * @deprecated use {@link DateFormat}
+ * @deprecated Use {@link DateFormat} instead.
*/
@Deprecated
public static long parse(String string) {
@@ -569,7 +566,7 @@
* @param day
* the day of the month.
*
- * @deprecated use {@code Calendar.set(Calendar.DATE, day)}
+ * @deprecated Use {@code Calendar.set(Calendar.DATE, day)} instead.
*/
@Deprecated
public void setDate(int day) {
@@ -584,7 +581,7 @@
* @param hour
* the hour of the day.
*
- * @deprecated use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)}
+ * @deprecated Use {@code Calendar.set(Calendar.HOUR_OF_DAY, hour)} instead.
*/
@Deprecated
public void setHours(int hour) {
@@ -599,7 +596,7 @@
* @param minute
* the minutes.
*
- * @deprecated use {@code Calendar.set(Calendar.MINUTE, minute)}
+ * @deprecated Use {@code Calendar.set(Calendar.MINUTE, minute)} instead.
*/
@Deprecated
public void setMinutes(int minute) {
@@ -614,7 +611,7 @@
* @param month
* the month.
*
- * @deprecated use {@code Calendar.set(Calendar.MONTH, month)}
+ * @deprecated Use {@code Calendar.set(Calendar.MONTH, month)} instead.
*/
@Deprecated
public void setMonth(int month) {
@@ -629,7 +626,7 @@
* @param second
* the seconds.
*
- * @deprecated use {@code Calendar.set(Calendar.SECOND, second)}
+ * @deprecated Use {@code Calendar.set(Calendar.SECOND, second)} instead.
*/
@Deprecated
public void setSeconds(int second) {
@@ -655,7 +652,7 @@
* @param year
* the year since 1900.
*
- * @deprecated use {@code Calendar.set(Calendar.YEAR, year + 1900)}
+ * @deprecated Use {@code Calendar.set(Calendar.YEAR, year + 1900)} instead.
*/
@Deprecated
public void setYear(int year) {
@@ -668,7 +665,7 @@
* Returns the string representation of this {@code Date} in GMT in the format
* {@code "22 Jun 1999 13:02:00 GMT"}.
*
- * @deprecated use {@link DateFormat}
+ * @deprecated Use {@link DateFormat} instead.
*/
@Deprecated
public String toGMTString() {
@@ -683,7 +680,7 @@
/**
* Returns the string representation of this {@code Date} for the default {@code Locale}.
*
- * @deprecated use {@link DateFormat}
+ * @deprecated Use {@link DateFormat} instead.
*/
@Deprecated
public String toLocaleString() {
@@ -749,7 +746,7 @@
* the second of the minute, 0 - 59.
* @return the date and time in GMT in milliseconds.
*
- * @deprecated use: <code>
+ * @deprecated Use code like this instead:<code>
* Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
* cal.set(year + 1900, month, day, hour, minute, second);
* cal.getTime().getTime();</code>
diff --git a/luni/src/main/java/java/util/EnumSet.java b/luni/src/main/java/java/util/EnumSet.java
index 20be6f7..0393511 100644
--- a/luni/src/main/java/java/util/EnumSet.java
+++ b/luni/src/main/java/java/util/EnumSet.java
@@ -259,6 +259,7 @@
* @throws NullPointerException
* if any of the specified elements is {@code null}.
*/
+ @SafeVarargs
public static <E extends Enum<E>> EnumSet<E> of(E start, E... others) {
EnumSet<E> set = of(start);
for (E e : others) {
diff --git a/luni/src/main/java/java/util/Formatter.java b/luni/src/main/java/java/util/Formatter.java
index d6b772a..98bdccc 100644
--- a/luni/src/main/java/java/util/Formatter.java
+++ b/luni/src/main/java/java/util/Formatter.java
@@ -291,7 +291,7 @@
* </tr>
* <tr>
* <td width="5%">{@code n}</td>
- * <td width="25%">Newline. (The value of the "line.separator" system property}.)</td>
+ * <td width="25%">Newline. (The value of {@link System#lineSeparator}.)</td>
* <td width="30%">{@code format("first%nsecond");}</td>
* <td width="30%">{@code first\nsecond}</td>
* </tr>
diff --git a/luni/src/main/java/java/util/NavigableMap.java b/luni/src/main/java/java/util/NavigableMap.java
index beeb651..8530530 100644
--- a/luni/src/main/java/java/util/NavigableMap.java
+++ b/luni/src/main/java/java/util/NavigableMap.java
@@ -55,7 +55,7 @@
* implement {@code NavigableMap}, but extensions and implementations
* of this interface are encouraged to override these methods to return
* {@code NavigableMap}. Similarly,
- * {@link #keySet()} can be overriden to return {@code NavigableSet}.
+ * {@link #keySet()} can be overridden to return {@code NavigableSet}.
*
* @author Doug Lea
* @author Josh Bloch
@@ -183,18 +183,12 @@
/**
* Returns a key-value mapping associated with the least
* key in this map, or {@code null} if the map is empty.
- *
- * @return an entry with the least key,
- * or {@code null} if this map is empty
*/
Map.Entry<K,V> firstEntry();
/**
* Returns a key-value mapping associated with the greatest
* key in this map, or {@code null} if the map is empty.
- *
- * @return an entry with the greatest key,
- * or {@code null} if this map is empty
*/
Map.Entry<K,V> lastEntry();
diff --git a/luni/src/main/java/java/util/Objects.java b/luni/src/main/java/java/util/Objects.java
new file mode 100644
index 0000000..2bfcef5
--- /dev/null
+++ b/luni/src/main/java/java/util/Objects.java
@@ -0,0 +1,127 @@
+/*
+ * 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 java.util;
+
+import java.util.Arrays;
+
+/**
+ * Utility methods for objects.
+ * @since 1.7
+ */
+public final class Objects {
+ private Objects() {}
+
+ /**
+ * Returns 0 if {@code a == b}, or {@code c.compare(a, b)} otherwise.
+ * That is, this makes {@code c} null-safe.
+ */
+ public static <T> int compare(T a, T b, Comparator<? super T> c) {
+ if (a == b) {
+ return 0;
+ }
+ return c.compare(a, b);
+ }
+
+ /**
+ * Returns true if both arguments are null,
+ * the result of {@link Arrays#equals} if both arguments are primitive arrays,
+ * the result of {@link Arrays#deepEquals} if both arguments are arrays of reference types,
+ * and the result of {@link #equals} otherwise.
+ */
+ public static boolean deepEquals(Object a, Object b) {
+ if (a == null || b == null) {
+ return a == b;
+ } else if (a instanceof Object[] && b instanceof Object[]) {
+ return Arrays.deepEquals((Object[]) a, (Object[]) b);
+ } else if (a instanceof boolean[] && b instanceof boolean[]) {
+ return Arrays.equals((boolean[]) a, (boolean[]) b);
+ } else if (a instanceof byte[] && b instanceof byte[]) {
+ return Arrays.equals((byte[]) a, (byte[]) b);
+ } else if (a instanceof char[] && b instanceof char[]) {
+ return Arrays.equals((char[]) a, (char[]) b);
+ } else if (a instanceof double[] && b instanceof double[]) {
+ return Arrays.equals((double[]) a, (double[]) b);
+ } else if (a instanceof float[] && b instanceof float[]) {
+ return Arrays.equals((float[]) a, (float[]) b);
+ } else if (a instanceof int[] && b instanceof int[]) {
+ return Arrays.equals((int[]) a, (int[]) b);
+ } else if (a instanceof long[] && b instanceof long[]) {
+ return Arrays.equals((long[]) a, (long[]) b);
+ } else if (a instanceof short[] && b instanceof short[]) {
+ return Arrays.equals((short[]) a, (short[]) b);
+ }
+ return a.equals(b);
+ }
+
+ /**
+ * Null-safe equivalent of {@code a.equals(b)}.
+ */
+ public static boolean equals(Object a, Object b) {
+ return (a == null) ? (b == null) : a.equals(b);
+ }
+
+ /**
+ * Convenience wrapper for {@link Arrays#hashCode}, adding varargs.
+ * This can be used to compute a hash code for an object's fields as follows:
+ * {@code Objects.hash(a, b, c)}.
+ */
+ public static int hash(Object... values) {
+ return Arrays.hashCode(values);
+ }
+
+ /**
+ * Returns 0 for null or {@code o.hashCode()}.
+ */
+ public static int hashCode(Object o) {
+ return (o == null) ? 0 : o.hashCode();
+ }
+
+ /**
+ * Returns {@code o} if non-null, or throws {@code NullPointerException}.
+ */
+ public static <T> T requireNonNull(T o) {
+ if (o == null) {
+ throw new NullPointerException();
+ }
+ return o;
+ }
+
+ /**
+ * Returns {@code o} if non-null, or throws {@code NullPointerException}
+ * with the given detail message.
+ */
+ public static <T> T requireNonNull(T o, String message) {
+ if (o == null) {
+ throw new NullPointerException(message);
+ }
+ return o;
+ }
+
+ /**
+ * Returns "null" for null or {@code o.toString()}.
+ */
+ public static String toString(Object o) {
+ return (o == null) ? "null" : o.toString();
+ }
+
+ /**
+ * Returns {@code nullString} for null or {@code o.toString()}.
+ */
+ public static String toString(Object o, String nullString) {
+ return (o == null) ? nullString : o.toString();
+ }
+}
diff --git a/luni/src/main/java/java/util/Properties.java b/luni/src/main/java/java/util/Properties.java
index 57c6a00..cd19295 100644
--- a/luni/src/main/java/java/util/Properties.java
+++ b/luni/src/main/java/java/util/Properties.java
@@ -486,7 +486,7 @@
* @throws ClassCastException if the key or value of a mapping is not a
* String.
* @deprecated This method ignores any {@code IOException} thrown while
- * writing -- use {@link #store} instead for better exception
+ * writing — use {@link #store} instead for better exception
* handling.
*/
@Deprecated
diff --git a/luni/src/main/java/java/util/ResourceBundle.java b/luni/src/main/java/java/util/ResourceBundle.java
index f5c8285..a9c5824 100644
--- a/luni/src/main/java/java/util/ResourceBundle.java
+++ b/luni/src/main/java/java/util/ResourceBundle.java
@@ -24,8 +24,7 @@
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
-import java.nio.charset.Charsets;
-import static java.nio.charset.Charsets.UTF_8;
+import java.nio.charset.StandardCharsets;
import libcore.io.IoUtils;
/**
@@ -518,7 +517,7 @@
: ClassLoader.getSystemResourceAsStream(fileName);
if (stream != null) {
try {
- bundle = new PropertyResourceBundle(new InputStreamReader(stream, UTF_8));
+ bundle = new PropertyResourceBundle(new InputStreamReader(stream, StandardCharsets.UTF_8));
bundle.setLocale(locale);
} catch (IOException ignored) {
} finally {
diff --git a/luni/src/main/java/java/util/Scanner.java b/luni/src/main/java/java/util/Scanner.java
index 5f7d0e3..972e6f9 100644
--- a/luni/src/main/java/java/util/Scanner.java
+++ b/luni/src/main/java/java/util/Scanner.java
@@ -31,6 +31,7 @@
import java.nio.channels.ReadableByteChannel;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
@@ -39,62 +40,49 @@
/**
* A parser that parses a text string of primitive types and strings with the
- * help of regular expressions. It supports localized numbers and various
+ * help of regular expressions. This class is not as useful as it might seem.
+ * It's very inefficient for communicating between machines; you should use JSON,
+ * protobufs, or even XML for that. Very simple uses might get away with {@link String#split}.
+ * For input from humans, the use of locale-specific regular expressions make it not only
+ * expensive but also somewhat unpredictable.
+ *
+ * <p>This class supports localized numbers and various
* radixes. The input is broken into tokens by the delimiter pattern, which is
- * whitespace by default. The primitive types can be obtained via corresponding
- * next* methods. If the token is not in a valid format, an
- * {@code InputMismatchException} is thrown.
- * <p>
- * For example:
+ * {@code \\p{javaWhitespace}} by default.
+ *
+ * <p>Example:
* <pre>
* Scanner s = new Scanner("1A true");
- * System.out.println(s.nextInt(16));
- * System.out.println(s.nextBoolean());
+ * assertEquals(26, s.nextInt(16));
+ * assertEquals(true, s.nextBoolean());
* </pre>
- * <p>
- * Yields the result: {@code 26 true}
- * <p>A {@code Scanner} can also find or skip specific patterns without regard for the
- * delimiter. All these methods and the various next* and hasNext* methods may
- * block.
- * <p>
- * The {@code Scanner} class is not thread-safe.
+ *
+ * <p>The {@code Scanner} class is not thread-safe.
*/
-public final class Scanner implements Iterator<String> {
+public final class Scanner implements Closeable, Iterator<String> {
+
+ private static final String NL = "\n|\r\n|\r|\u0085|\u2028|\u2029";
// Default delimiting pattern.
- private static final Pattern DEFAULT_DELIMITER = Pattern
- .compile("\\p{javaWhitespace}+");
+ private static final Pattern DEFAULT_DELIMITER = Pattern.compile("\\p{javaWhitespace}+");
// The boolean's pattern.
- private static final Pattern BOOLEAN_PATTERN = Pattern.compile(
- "true|false", Pattern.CASE_INSENSITIVE);
+ private static final Pattern BOOLEAN_PATTERN = Pattern.compile("true|false", Pattern.CASE_INSENSITIVE);
// Pattern used to recognize line terminator.
- private static final Pattern LINE_TERMINATOR;
+ private static final Pattern LINE_TERMINATOR = Pattern.compile(NL);
// Pattern used to recognize multiple line terminators.
- private static final Pattern MULTI_LINE_TERMINATOR;
+ 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;
-
- static {
- String NL = "\n|\r\n|\r|\u0085|\u2028|\u2029";
- LINE_TERMINATOR = Pattern.compile(NL);
- MULTI_LINE_TERMINATOR = Pattern.compile("(" + NL + ")+");
- LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+(" + NL + ")?");
- }
+ private static final Pattern LINE_PATTERN = Pattern.compile(".*(" + NL + ")|.+(" + NL + ")?");
// The pattern matches anything.
private static final Pattern ANY_PATTERN = Pattern.compile("(?s).*");
- private static final int DIPLOID = 2;
-
- // Default radix.
private static final int DEFAULT_RADIX = 10;
- private static final int DEFAULT_TRUNK_SIZE = 1024;
-
// The input source of scanner.
private Readable input;
@@ -104,7 +92,7 @@
private Matcher matcher;
- private int integerRadix = DEFAULT_RADIX;
+ private int currentRadix = DEFAULT_RADIX;
private Locale locale = Locale.getDefault();
@@ -117,8 +105,7 @@
// The length of the buffer.
private int bufferLength = 0;
- // Record the status of this scanner. True if the scanner
- // is closed.
+ // Record the status of this scanner. True if the scanner is closed.
private boolean closed = false;
private IOException lastIOException;
@@ -130,9 +117,13 @@
// Records whether the underlying readable has more input.
private boolean inputExhausted = false;
- private Object cacheHasNextValue = null;
+ private Object cachedNextValue = null;
+ private int cachedNextIndex = -1;
- private int cachehasNextIndex = -1;
+ private Pattern cachedFloatPattern = null;
+
+ private int cachedIntegerPatternRadix = -1;
+ private Pattern cachedIntegerPattern = null;
private enum DataType {
/*
@@ -327,8 +318,8 @@
* if the {@code Scanner} is closed.
*/
public String findInLine(Pattern pattern) {
- checkClosed();
- checkNull(pattern);
+ checkOpen();
+ checkNotNull(pattern);
int horizonLineSeparator = 0;
matcher.usePattern(MULTI_LINE_TERMINATOR);
@@ -405,7 +396,7 @@
}
/**
- * Compiles the pattern string and tries to find a substing matching it in the input data. The
+ * Compiles the pattern string and tries to find a substring matching it in the input data. The
* delimiter will be ignored. This is the same as invoking
* {@code findInLine(Pattern.compile(pattern))}.
*
@@ -455,8 +446,8 @@
* if {@code horizon} is less than zero.
*/
public String findWithinHorizon(Pattern pattern, int horizon) {
- checkClosed();
- checkNull(pattern);
+ checkOpen();
+ checkNotNull(pattern);
if (horizon < 0) {
throw new IllegalArgumentException("horizon < 0");
}
@@ -559,8 +550,8 @@
* if the {@code Scanner} has been closed.
*/
public boolean hasNext(Pattern pattern) {
- checkClosed();
- checkNull(pattern);
+ checkOpen();
+ checkNotNull(pattern);
matchSuccessful = false;
saveCurrentStatus();
// if the next token exists, set the match region, otherwise return
@@ -573,7 +564,7 @@
boolean hasNext = false;
// check whether next token matches the specified pattern
if (matcher.matches()) {
- cachehasNextIndex = findStartIndex;
+ cachedNextIndex = findStartIndex;
matchSuccessful = true;
hasNext = true;
}
@@ -614,7 +605,7 @@
String floatString = matcher.group();
floatString = removeLocaleInfoFromFloat(floatString);
try {
- cacheHasNextValue = new BigDecimal(floatString);
+ cachedNextValue = new BigDecimal(floatString);
isBigDecimalValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -633,7 +624,7 @@
* if the {@code Scanner} has been closed.
*/
public boolean hasNextBigInteger() {
- return hasNextBigInteger(integerRadix);
+ return hasNextBigInteger(currentRadix);
}
/**
@@ -655,7 +646,7 @@
String intString = matcher.group();
intString = removeLocaleInfo(intString, DataType.INT);
try {
- cacheHasNextValue = new BigInteger(intString, radix);
+ cachedNextValue = new BigInteger(intString, radix);
isBigIntegerValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -687,7 +678,7 @@
* if the {@code Scanner} has been closed.
*/
public boolean hasNextByte() {
- return hasNextByte(integerRadix);
+ return hasNextByte(currentRadix);
}
/**
@@ -709,7 +700,7 @@
String intString = matcher.group();
intString = removeLocaleInfo(intString, DataType.INT);
try {
- cacheHasNextValue = Byte.valueOf(intString, radix);
+ cachedNextValue = Byte.valueOf(intString, radix);
isByteValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -734,7 +725,7 @@
String floatString = matcher.group();
floatString = removeLocaleInfoFromFloat(floatString);
try {
- cacheHasNextValue = Double.valueOf(floatString);
+ cachedNextValue = Double.valueOf(floatString);
isDoubleValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -759,7 +750,7 @@
String floatString = matcher.group();
floatString = removeLocaleInfoFromFloat(floatString);
try {
- cacheHasNextValue = Float.valueOf(floatString);
+ cachedNextValue = Float.valueOf(floatString);
isFloatValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -778,7 +769,7 @@
* if the {@code Scanner} has been closed,
*/
public boolean hasNextInt() {
- return hasNextInt(integerRadix);
+ return hasNextInt(currentRadix);
}
/**
@@ -801,7 +792,7 @@
String intString = matcher.group();
intString = removeLocaleInfo(intString, DataType.INT);
try {
- cacheHasNextValue = Integer.valueOf(intString, radix);
+ cachedNextValue = Integer.valueOf(intString, radix);
isIntValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -820,7 +811,7 @@
* if the {@code Scanner} is closed.
*/
public boolean hasNextLine() {
- checkClosed();
+ checkOpen();
matcher.usePattern(LINE_PATTERN);
matcher.region(findStartIndex, bufferLength);
@@ -856,7 +847,7 @@
* if the {@code Scanner} has been closed.
*/
public boolean hasNextLong() {
- return hasNextLong(integerRadix);
+ return hasNextLong(currentRadix);
}
/**
@@ -878,7 +869,7 @@
String intString = matcher.group();
intString = removeLocaleInfo(intString, DataType.INT);
try {
- cacheHasNextValue = Long.valueOf(intString, radix);
+ cachedNextValue = Long.valueOf(intString, radix);
isLongValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -897,7 +888,7 @@
* if the {@code Scanner} has been closed.
*/
public boolean hasNextShort() {
- return hasNextShort(integerRadix);
+ return hasNextShort(currentRadix);
}
/**
@@ -919,7 +910,7 @@
String intString = matcher.group();
intString = removeLocaleInfo(intString, DataType.INT);
try {
- cacheHasNextValue = Short.valueOf(intString, radix);
+ cachedNextValue = Short.valueOf(intString, radix);
isShortValue = true;
} catch (NumberFormatException e) {
matchSuccessful = false;
@@ -930,23 +921,27 @@
/**
* Returns the last {@code IOException} that was raised while reading from the underlying
- * input.
- *
- * @return the last thrown {@code IOException}, or {@code null} if none was thrown.
+ * input, or {@code null} if none was thrown.
*/
public IOException ioException() {
return lastIOException;
}
/**
- * Return the {@code Locale} of this {@code Scanner}.
- *
- * @return the {@code Locale} of this {@code Scanner}.
+ * Returns the {@code Locale} of this {@code Scanner}.
*/
public Locale locale() {
return locale;
}
+ private void setLocale(Locale locale) {
+ this.locale = locale;
+ this.decimalFormat = null;
+ this.cachedFloatPattern = null;
+ this.cachedIntegerPatternRadix = -1;
+ this.cachedIntegerPattern = null;
+ }
+
/**
* Returns the result of the last matching operation.
* <p>
@@ -966,7 +961,7 @@
}
/**
- * Returns the next token. The token will be both prefixed and postfixed by
+ * Returns the next token. The token will be both prefixed and suffixed by
* the delimiter that is currently being used (or a string that matches the
* delimiter pattern). This method will block if input is being read.
*
@@ -982,7 +977,7 @@
/**
* Returns the next token if it matches the specified pattern. The token
- * will be both prefixed and postfixed by the delimiter that is currently
+ * will be both prefixed and suffixed by the delimiter that is currently
* being used (or a string that matches the delimiter pattern). This method will block
* if input is being read.
*
@@ -997,8 +992,8 @@
* if the next token does not match the pattern given.
*/
public String next(Pattern pattern) {
- checkClosed();
- checkNull(pattern);
+ checkOpen();
+ checkNotNull(pattern);
matchSuccessful = false;
saveCurrentStatus();
if (!setTokenRegion()) {
@@ -1018,7 +1013,7 @@
/**
* Returns the next token if it matches the specified pattern. The token
- * will be both prefixed and postfixed by the delimiter that is currently
+ * will be both prefixed and suffixed by the delimiter that is currently
* being used (or a string that matches the delimiter pattern). This method will block
* if input is being read. Calling this method is equivalent to
* {@code next(Pattern.compile(pattern))}.
@@ -1057,11 +1052,11 @@
* {@code BigDecimal}.
*/
public BigDecimal nextBigDecimal() {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof BigDecimal) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (BigDecimal) obj;
}
Pattern floatPattern = getFloatPattern();
@@ -1079,10 +1074,9 @@
}
/**
- * Returns the next token as a {@code BigInteger}. This method will block if input is
- * being read. Equivalent to {@code nextBigInteger(DEFAULT_RADIX)}.
+ * Returns the next token as a {@code BigInteger} in the current radix.
+ * This method may block for more input.
*
- * @return the next token as {@code BigInteger}.
* @throws IllegalStateException
* if this {@code Scanner} has been closed.
* @throws NoSuchElementException
@@ -1092,7 +1086,7 @@
* {@code BigInteger}.
*/
public BigInteger nextBigInteger() {
- return nextBigInteger(integerRadix);
+ return nextBigInteger(currentRadix);
}
/**
@@ -1119,11 +1113,11 @@
* {@code BigInteger}.
*/
public BigInteger nextBigInteger(int radix) {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof BigInteger) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (BigInteger) obj;
}
Pattern integerPattern = getIntegerPattern(radix);
@@ -1158,10 +1152,9 @@
}
/**
- * Returns the next token as a {@code byte}. This method will block if input is being
- * read. Equivalent to {@code nextByte(DEFAULT_RADIX)}.
+ * Returns the next token as a {@code byte} in the current radix.
+ * This method may block for more input.
*
- * @return the next token as a {@code byte}.
* @throws IllegalStateException
* if this {@code Scanner} has been closed.
* @throws NoSuchElementException
@@ -1171,7 +1164,7 @@
* {@code byte} value.
*/
public byte nextByte() {
- return nextByte(integerRadix);
+ return nextByte(currentRadix);
}
/**
@@ -1198,11 +1191,11 @@
*/
@SuppressWarnings("boxing")
public byte nextByte(int radix) {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Byte) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Byte) obj;
}
Pattern integerPattern = getIntegerPattern(radix);
@@ -1242,11 +1235,11 @@
*/
@SuppressWarnings("boxing")
public double nextDouble() {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Double) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Double) obj;
}
Pattern floatPattern = getFloatPattern();
@@ -1286,11 +1279,11 @@
*/
@SuppressWarnings("boxing")
public float nextFloat() {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Float) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Float) obj;
}
Pattern floatPattern = getFloatPattern();
@@ -1308,10 +1301,9 @@
}
/**
- * Returns the next token as an {@code int}. This method will block if input is being
- * read. Equivalent to {@code nextInt(DEFAULT_RADIX)}.
+ * Returns the next token as an {@code int} in the current radix.
+ * This method may block for more input.
*
- * @return the next token as an {@code int}
* @throws IllegalStateException
* if this {@code Scanner} has been closed.
* @throws NoSuchElementException
@@ -1321,7 +1313,7 @@
* {@code int} value.
*/
public int nextInt() {
- return nextInt(integerRadix);
+ return nextInt(currentRadix);
}
/**
@@ -1349,11 +1341,11 @@
*/
@SuppressWarnings("boxing")
public int nextInt(int radix) {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Integer) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Integer) obj;
}
Pattern integerPattern = getIntegerPattern(radix);
@@ -1384,7 +1376,7 @@
* if no line can be found, e.g. when input is an empty string.
*/
public String nextLine() {
- checkClosed();
+ checkOpen();
matcher.usePattern(LINE_PATTERN);
matcher.region(findStartIndex, bufferLength);
@@ -1420,10 +1412,9 @@
}
/**
- * Returns the next token as a {@code long}. This method will block if input is being
- * read. Equivalent to {@code nextLong(DEFAULT_RADIX)}.
+ * Returns the next token as a {@code long} in the current radix.
+ * This method may block for more input.
*
- * @return the next token as a {@code long}.
* @throws IllegalStateException
* if this {@code Scanner} has been closed.
* @throws NoSuchElementException
@@ -1433,7 +1424,7 @@
* {@code long} value.
*/
public long nextLong() {
- return nextLong(integerRadix);
+ return nextLong(currentRadix);
}
/**
@@ -1461,11 +1452,11 @@
*/
@SuppressWarnings("boxing")
public long nextLong(int radix) {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Long) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Long) obj;
}
Pattern integerPattern = getIntegerPattern(radix);
@@ -1483,10 +1474,9 @@
}
/**
- * Returns the next token as a {@code short}. This method will block if input is being
- * read. Equivalent to {@code nextShort(DEFAULT_RADIX)}.
+ * Returns the next token as a {@code short} in the current radix.
+ * This method may block for more input.
*
- * @return the next token as a {@code short}.
* @throws IllegalStateException
* if this {@code Scanner} has been closed.
* @throws NoSuchElementException
@@ -1496,7 +1486,7 @@
* {@code short} value.
*/
public short nextShort() {
- return nextShort(integerRadix);
+ return nextShort(currentRadix);
}
/**
@@ -1524,11 +1514,11 @@
*/
@SuppressWarnings("boxing")
public short nextShort(int radix) {
- checkClosed();
- Object obj = cacheHasNextValue;
- cacheHasNextValue = null;
+ checkOpen();
+ Object obj = cachedNextValue;
+ cachedNextValue = null;
if (obj instanceof Short) {
- findStartIndex = cachehasNextIndex;
+ findStartIndex = cachedNextIndex;
return (Short) obj;
}
Pattern integerPattern = getIntegerPattern(radix);
@@ -1551,7 +1541,7 @@
* @return the radix of this {@code Scanner}
*/
public int radix() {
- return integerRadix;
+ return currentRadix;
}
/**
@@ -1571,8 +1561,8 @@
* if the specified pattern match fails.
*/
public Scanner skip(Pattern pattern) {
- checkClosed();
- checkNull(pattern);
+ checkOpen();
+ checkNotNull(pattern);
matcher.usePattern(pattern);
matcher.region(findStartIndex, bufferLength);
while (true) {
@@ -1666,7 +1656,7 @@
if (l == null) {
throw new NullPointerException("l == null");
}
- this.locale = l;
+ setLocale(l);
return this;
}
@@ -1679,7 +1669,7 @@
*/
public Scanner useRadix(int radix) {
checkRadix(radix);
- this.integerRadix = radix;
+ this.currentRadix = radix;
return this;
}
@@ -1703,26 +1693,18 @@
* Initialize some components.
*/
private void initialization() {
- buffer = CharBuffer.allocate(DEFAULT_TRUNK_SIZE);
+ buffer = CharBuffer.allocate(1024);
buffer.limit(0);
matcher = delimiter.matcher(buffer);
}
- /*
- * Check the {@code Scanner}'s state, if it is closed, IllegalStateException will be
- * thrown.
- */
- private void checkClosed() {
+ private void checkOpen() {
if (closed) {
throw new IllegalStateException();
}
}
- /*
- * Check the inputed pattern. If it is null, then a NullPointerException
- * will be thrown out.
- */
- private void checkNull(Pattern pattern) {
+ private void checkNotNull(Pattern pattern) {
if (pattern == null) {
throw new NullPointerException("pattern == null");
}
@@ -1754,93 +1736,82 @@
findStartIndex = preStartIndex;
}
- /*
- * Get integer's pattern
- */
private Pattern getIntegerPattern(int radix) {
checkRadix(radix);
- decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
- String allAvailableDigits = "0123456789abcdefghijklmnopqrstuvwxyz";
- String ASCIIDigit = allAvailableDigits.substring(0, radix);
- String nonZeroASCIIDigit = allAvailableDigits.substring(1, radix);
+ if (decimalFormat == null) {
+ decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+ }
- StringBuilder digit = new StringBuilder("((?i)[").append(ASCIIDigit)
- .append("]|\\p{javaDigit})");
- StringBuilder nonZeroDigit = new StringBuilder("((?i)[").append(
- nonZeroASCIIDigit).append("]|([\\p{javaDigit}&&[^0]]))");
- StringBuilder numeral = getNumeral(digit, nonZeroDigit);
+ if (cachedIntegerPatternRadix == radix) {
+ return cachedIntegerPattern;
+ }
- StringBuilder integer = new StringBuilder("(([-+]?(").append(numeral)
- .append(")))|(").append(addPositiveSign(numeral)).append(")|(")
- .append(addNegativeSign(numeral)).append(")");
+ String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
+ String ASCIIDigit = digits.substring(0, radix);
+ String nonZeroASCIIDigit = digits.substring(1, radix);
- Pattern integerPattern = Pattern.compile(integer.toString());
- return integerPattern;
+ String digit = "((?i)[" + ASCIIDigit + "]|\\p{javaDigit})";
+ String nonZeroDigit = "((?i)[" + nonZeroASCIIDigit + "]|([\\p{javaDigit}&&[^0]]))";
+ String numeral = getNumeral(digit, nonZeroDigit);
+
+ String regex = "(([-+]?(" + numeral + ")))|" +
+ "(" + addPositiveSign(numeral) + ")|" +
+ "(" + addNegativeSign(numeral) + ")";
+
+ cachedIntegerPatternRadix = radix;
+ cachedIntegerPattern = Pattern.compile(regex);
+ return cachedIntegerPattern;
}
- /*
- * Get pattern of float
- */
private Pattern getFloatPattern() {
- decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+ if (decimalFormat == null) {
+ decimalFormat = (DecimalFormat) NumberFormat.getInstance(locale);
+ }
- StringBuilder digit = new StringBuilder("([0-9]|(\\p{javaDigit}))");
- StringBuilder nonZeroDigit = new StringBuilder("[\\p{javaDigit}&&[^0]]");
- StringBuilder numeral = getNumeral(digit, nonZeroDigit);
+ if (cachedFloatPattern != null) {
+ return cachedFloatPattern;
+ }
- String decimalSeparator = "\\" + decimalFormat.getDecimalFormatSymbols()
- .getDecimalSeparator();
- StringBuilder decimalNumeral = new StringBuilder("(").append(numeral)
- .append("|").append(numeral)
- .append(decimalSeparator).append(digit).append("*+|").append(
- decimalSeparator).append(digit).append("++)");
- StringBuilder exponent = new StringBuilder("([eE][+-]?").append(digit)
- .append("+)?");
+ DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
- StringBuilder decimal = new StringBuilder("(([-+]?").append(
- decimalNumeral).append("(").append(exponent).append("?)")
- .append(")|(").append(addPositiveSign(decimalNumeral)).append(
- "(").append(exponent).append("?)").append(")|(")
- .append(addNegativeSign(decimalNumeral)).append("(").append(
- exponent).append("?)").append("))");
+ String digit = "([0-9]|(\\p{javaDigit}))";
+ String nonZeroDigit = "[\\p{javaDigit}&&[^0]]";
+ String numeral = getNumeral(digit, nonZeroDigit);
- StringBuilder hexFloat = new StringBuilder("([-+]?0[xX][0-9a-fA-F]*")
- .append("\\.").append(
- "[0-9a-fA-F]+([pP][-+]?[0-9]+)?)");
- String localNaN = decimalFormat.getDecimalFormatSymbols().getNaN();
- String localeInfinity = decimalFormat.getDecimalFormatSymbols()
- .getInfinity();
- StringBuilder nonNumber = new StringBuilder("(NaN|\\Q").append(localNaN)
- .append("\\E|Infinity|\\Q").append(localeInfinity).append("\\E)");
- StringBuilder singedNonNumber = new StringBuilder("((([-+]?(").append(
- nonNumber).append(")))|(").append(addPositiveSign(nonNumber))
- .append(")|(").append(addNegativeSign(nonNumber)).append("))");
+ String decimalSeparator = "\\" + dfs.getDecimalSeparator();
+ String decimalNumeral = "(" + numeral + "|" +
+ numeral + decimalSeparator + digit + "*+|" +
+ decimalSeparator + digit + "++)";
+ String exponent = "([eE][+-]?" + digit + "+)?";
- StringBuilder floatString = new StringBuilder().append(decimal).append(
- "|").append(hexFloat).append("|").append(singedNonNumber);
- Pattern floatPattern = Pattern.compile(floatString.toString());
- return floatPattern;
+ String decimal = "(([-+]?" + decimalNumeral + "(" + exponent + "?)" + ")|" +
+ "(" + addPositiveSign(decimalNumeral) + "(" + exponent + "?)" + ")|" +
+ "(" + addNegativeSign(decimalNumeral) + "(" + exponent + "?)" + "))";
+
+ String hexFloat = "([-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?)";
+ String localNaN = dfs.getNaN();
+ String localeInfinity = dfs.getInfinity();
+ String nonNumber = "(NaN|\\Q" + localNaN + "\\E|Infinity|\\Q" + localeInfinity + "\\E)";
+ String signedNonNumber = "((([-+]?(" + nonNumber + ")))|" +
+ "(" + addPositiveSign(nonNumber) + ")|" +
+ "(" + addNegativeSign(nonNumber) + "))";
+
+ cachedFloatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + signedNonNumber);
+ return cachedFloatPattern;
}
- private StringBuilder getNumeral(StringBuilder digit,
- StringBuilder nonZeroDigit) {
- String groupSeparator = "\\"
- + decimalFormat.getDecimalFormatSymbols()
- .getGroupingSeparator();
- StringBuilder groupedNumeral = new StringBuilder("(").append(
- nonZeroDigit).append(digit).append("?").append(digit).append(
- "?(").append(groupSeparator).append(digit).append(digit)
- .append(digit).append(")+)");
- StringBuilder numeral = new StringBuilder("((").append(digit).append(
- "++)|").append(groupedNumeral).append(")");
- return numeral;
+ private String getNumeral(String digit, String nonZeroDigit) {
+ String groupSeparator = "\\" + decimalFormat.getDecimalFormatSymbols().getGroupingSeparator();
+ String groupedNumeral = "(" + nonZeroDigit + digit + "?" + digit + "?" +
+ "(" + groupSeparator + digit + digit + digit + ")+)";
+ return "((" + digit + "++)|" + groupedNumeral + ")";
}
/*
* Add the locale specific positive prefixes and suffixes to the pattern
*/
- private StringBuilder addPositiveSign(StringBuilder unSignNumeral) {
+ private String addPositiveSign(String unsignedNumeral) {
String positivePrefix = "";
String positiveSuffix = "";
if (!decimalFormat.getPositivePrefix().isEmpty()) {
@@ -1849,16 +1820,13 @@
if (!decimalFormat.getPositiveSuffix().isEmpty()) {
positiveSuffix = "\\Q" + decimalFormat.getPositiveSuffix() + "\\E";
}
- StringBuilder signedNumeral = new StringBuilder()
- .append(positivePrefix).append(unSignNumeral).append(
- positiveSuffix);
- return signedNumeral;
+ return positivePrefix + unsignedNumeral + positiveSuffix;
}
/*
* Add the locale specific negative prefixes and suffixes to the pattern
*/
- private StringBuilder addNegativeSign(StringBuilder unSignNumeral) {
+ private String addNegativeSign(String unsignedNumeral) {
String negativePrefix = "";
String negativeSuffix = "";
if (!decimalFormat.getNegativePrefix().isEmpty()) {
@@ -1867,10 +1835,7 @@
if (!decimalFormat.getNegativeSuffix().isEmpty()) {
negativeSuffix = "\\Q" + decimalFormat.getNegativeSuffix() + "\\E";
}
- StringBuilder signedNumeral = new StringBuilder()
- .append(negativePrefix).append(unSignNumeral).append(
- negativeSuffix);
- return signedNumeral;
+ return negativePrefix + unsignedNumeral + negativeSuffix;
}
/*
@@ -1878,21 +1843,16 @@
*/
private String removeLocaleInfoFromFloat(String floatString) {
// If the token is HexFloat
- if (-1 != floatString.indexOf('x') || -1 != floatString.indexOf('X')) {
+ if (floatString.indexOf('x') != -1 || floatString.indexOf('X') != -1) {
return floatString;
}
- int exponentIndex;
- String decimalNumeralString;
- String exponentString;
// If the token is scientific notation
- if (-1 != (exponentIndex = floatString.indexOf('e'))
- || -1 != (exponentIndex = floatString.indexOf('E'))) {
- decimalNumeralString = floatString.substring(0, exponentIndex);
- exponentString = floatString.substring(exponentIndex + 1,
- floatString.length());
- decimalNumeralString = removeLocaleInfo(decimalNumeralString,
- DataType.FLOAT);
+ int exponentIndex;
+ 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);
return decimalNumeralString + "e" + exponentString;
}
return removeLocaleInfo(floatString, DataType.FLOAT);
@@ -1903,40 +1863,36 @@
* specific suffixes from input string
*/
private String removeLocaleInfo(String token, DataType type) {
+ DecimalFormatSymbols dfs = decimalFormat.getDecimalFormatSymbols();
+
StringBuilder tokenBuilder = new StringBuilder(token);
boolean negative = removeLocaleSign(tokenBuilder);
// Remove group separator
- String groupSeparator = String.valueOf(decimalFormat
- .getDecimalFormatSymbols().getGroupingSeparator());
+ String groupSeparator = String.valueOf(dfs.getGroupingSeparator());
int separatorIndex = -1;
- while (-1 != (separatorIndex = tokenBuilder.indexOf(groupSeparator))) {
+ while ((separatorIndex = tokenBuilder.indexOf(groupSeparator)) != -1) {
tokenBuilder.delete(separatorIndex, separatorIndex + 1);
}
// Remove decimal separator
- String decimalSeparator = String.valueOf(decimalFormat
- .getDecimalFormatSymbols().getDecimalSeparator());
+ String decimalSeparator = String.valueOf(dfs.getDecimalSeparator());
separatorIndex = tokenBuilder.indexOf(decimalSeparator);
StringBuilder result = new StringBuilder("");
if (DataType.INT == type) {
for (int i = 0; i < tokenBuilder.length(); i++) {
- if (-1 != Character.digit(tokenBuilder.charAt(i),
- Character.MAX_RADIX)) {
+ if (Character.digit(tokenBuilder.charAt(i), Character.MAX_RADIX) != -1) {
result.append(tokenBuilder.charAt(i));
}
}
}
if (DataType.FLOAT == type) {
- if (tokenBuilder.toString().equals(
- decimalFormat.getDecimalFormatSymbols().getNaN())) {
+ if (tokenBuilder.toString().equals(dfs.getNaN())) {
result.append("NaN");
- } else if (tokenBuilder.toString().equals(
- decimalFormat.getDecimalFormatSymbols().getInfinity())) {
+ } else if (tokenBuilder.toString().equals(dfs.getInfinity())) {
result.append("Infinity");
} else {
for (int i = 0; i < tokenBuilder.length(); i++) {
- if (-1 != Character.digit(tokenBuilder.charAt(i), 10)) {
- result.append(Character.digit(tokenBuilder.charAt(i),
- 10));
+ if (Character.digit(tokenBuilder.charAt(i), 10) != -1) {
+ result.append(Character.digit(tokenBuilder.charAt(i), 10));
}
}
}
@@ -1945,7 +1901,7 @@
if (result.length() == 0) {
result = tokenBuilder;
}
- if (-1 != separatorIndex) {
+ if (separatorIndex != -1) {
result.insert(separatorIndex, ".");
}
// If input is negative
@@ -1971,11 +1927,9 @@
if (!positivePrefix.isEmpty() && tokenBuilder.indexOf(positivePrefix) == 0) {
tokenBuilder.delete(0, positivePrefix.length());
}
- if (!positiveSuffix.isEmpty()
- && -1 != tokenBuilder.indexOf(positiveSuffix)) {
- tokenBuilder.delete(
- tokenBuilder.length() - positiveSuffix.length(),
- tokenBuilder.length());
+ if (!positiveSuffix.isEmpty() && tokenBuilder.indexOf(positiveSuffix) != -1) {
+ tokenBuilder.delete(tokenBuilder.length() - positiveSuffix.length(),
+ tokenBuilder.length());
}
boolean negative = false;
if (tokenBuilder.indexOf("-") == 0) {
@@ -1986,19 +1940,17 @@
tokenBuilder.delete(0, negativePrefix.length());
negative = true;
}
- if (!negativeSuffix.isEmpty()
- && -1 != tokenBuilder.indexOf(negativeSuffix)) {
- tokenBuilder.delete(
- tokenBuilder.length() - negativeSuffix.length(),
- tokenBuilder.length());
+ if (!negativeSuffix.isEmpty() && tokenBuilder.indexOf(negativeSuffix) != -1) {
+ tokenBuilder.delete(tokenBuilder.length() - negativeSuffix.length(),
+ tokenBuilder.length());
negative = true;
}
return negative;
}
/*
- * Find the prefixed delimiter and posefixed delimiter in the input resource
- * and set the start index and end index of Matcher region. If postfixed
+ * Find the prefixed delimiter and suffixed delimiter in the input resource
+ * and set the start index and end index of Matcher region. If the suffixed
* delimiter does not exist, the end index is set to be end of input.
*/
private boolean setTokenRegion() {
@@ -2014,7 +1966,7 @@
if (setHeadTokenRegion(tokenStartIndex)) {
return true;
}
- tokenEndIndex = findPostDelimiter();
+ tokenEndIndex = findDelimiterAfter();
// If the second delimiter is not found
if (-1 == tokenEndIndex) {
// Just first Delimiter Exists
@@ -2069,7 +2021,7 @@
int tokenStartIndex;
int tokenEndIndex;
boolean setSuccess = false;
- // If no delimiter exists, but something exites in this scanner
+ // If no delimiter exists, but something exists in this scanner
if (-1 == findIndex && preStartIndex != bufferLength) {
tokenStartIndex = preStartIndex;
tokenEndIndex = bufferLength;
@@ -2089,17 +2041,13 @@
return setSuccess;
}
- /*
- * Find postfix delimiter
- */
- private int findPostDelimiter() {
+ private int findDelimiterAfter() {
int tokenEndIndex = 0;
boolean findComplete = false;
while (!findComplete) {
if (matcher.find()) {
findComplete = true;
- if (matcher.start() == findStartIndex
- && matcher.start() == matcher.end()) {
+ if (matcher.start() == findStartIndex && matcher.start() == matcher.end()) {
findComplete = false;
}
} else {
@@ -2165,7 +2113,7 @@
int oldPosition = buffer.position();
int oldCapacity = buffer.capacity();
int oldLimit = buffer.limit();
- int newCapacity = oldCapacity * DIPLOID;
+ int newCapacity = oldCapacity * 2;
char[] newBuffer = new char[newCapacity];
System.arraycopy(buffer.array(), 0, newBuffer, 0, oldLimit);
buffer = CharBuffer.wrap(newBuffer, 0, newCapacity);
@@ -2181,8 +2129,8 @@
*/
public Scanner reset() {
delimiter = DEFAULT_DELIMITER;
- locale = Locale.getDefault();
- integerRadix = 10;
+ setLocale(Locale.getDefault());
+ currentRadix = DEFAULT_RADIX;
return this;
}
}
diff --git a/luni/src/main/java/java/util/SortedMap.java b/luni/src/main/java/java/util/SortedMap.java
index aec7adf..63acafd 100644
--- a/luni/src/main/java/java/util/SortedMap.java
+++ b/luni/src/main/java/java/util/SortedMap.java
@@ -25,16 +25,14 @@
public interface SortedMap<K,V> extends Map<K,V> {
/**
- * Returns the comparator used to compare keys in this sorted map.
- *
- * @return the comparator or {@code null} if the natural order is used.
+ * Returns the comparator used to compare keys in this sorted map, or null if the natural
+ * ordering is in use.
*/
public Comparator<? super K> comparator();
/**
- * Returns the first key in this sorted map.
+ * Returns the least key in this sorted map.
*
- * @return the first key in this sorted map.
* @throws NoSuchElementException
* if this sorted map is empty.
*/
@@ -64,9 +62,8 @@
public SortedMap<K,V> headMap(K endKey);
/**
- * Returns the last key in this sorted map.
+ * Returns the greatest key in this sorted map.
*
- * @return the last key in this sorted map.
* @throws NoSuchElementException
* if this sorted map is empty.
*/
diff --git a/luni/src/main/java/java/util/TimeZone.java b/luni/src/main/java/java/util/TimeZone.java
index 848ebbb..c024e8d 100644
--- a/luni/src/main/java/java/util/TimeZone.java
+++ b/luni/src/main/java/java/util/TimeZone.java
@@ -22,8 +22,12 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import libcore.icu.TimeZoneNames;
+import libcore.io.IoUtils;
import libcore.util.ZoneInfoDB;
+// TODO: repackage this class, used by frameworks/base.
+import org.apache.harmony.luni.internal.util.TimezoneGetter;
+
/**
* {@code TimeZone} represents a time zone, primarily used for configuring a {@link Calendar} or
* {@link java.text.SimpleDateFormat} instance.
@@ -105,7 +109,7 @@
* instance.
*/
public static synchronized String[] getAvailableIDs() {
- return ZoneInfoDB.getAvailableIDs();
+ return ZoneInfoDB.getInstance().getAvailableIDs();
}
/**
@@ -116,7 +120,7 @@
* @return a possibly-empty array.
*/
public static synchronized String[] getAvailableIDs(int offsetMillis) {
- return ZoneInfoDB.getAvailableIDs(offsetMillis);
+ return ZoneInfoDB.getInstance().getAvailableIDs(offsetMillis);
}
/**
@@ -128,7 +132,22 @@
*/
public static synchronized TimeZone getDefault() {
if (defaultTimeZone == null) {
- defaultTimeZone = ZoneInfoDB.getSystemDefault();
+ TimezoneGetter tzGetter = TimezoneGetter.getInstance();
+ String zoneName = (tzGetter != null) ? tzGetter.getId() : null;
+ if (zoneName != null) {
+ zoneName = zoneName.trim();
+ }
+ if (zoneName == null || zoneName.isEmpty()) {
+ try {
+ // On the host, we can find the configured timezone here.
+ zoneName = IoUtils.readFileAsString("/etc/timezone");
+ } catch (IOException ex) {
+ // "vogar --mode device" can end up here.
+ // TODO: give libcore access to Android system properties and read "persist.sys.timezone".
+ zoneName = "GMT";
+ }
+ }
+ defaultTimeZone = TimeZone.getTimeZone(zoneName);
}
return (TimeZone) defaultTimeZone.clone();
}
@@ -323,7 +342,7 @@
// In the database?
TimeZone zone = null;
try {
- zone = ZoneInfoDB.makeTimeZone(id);
+ zone = ZoneInfoDB.getInstance().makeTimeZone(id);
} catch (IOException ignored) {
}
diff --git a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
index a7f7745..23e68bb 100644
--- a/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/AbstractExecutorService.java
@@ -9,19 +9,19 @@
/**
* Provides default implementations of {@link ExecutorService}
- * execution methods. This class implements the <tt>submit</tt>,
- * <tt>invokeAny</tt> and <tt>invokeAll</tt> methods using a
- * {@link RunnableFuture} returned by <tt>newTaskFor</tt>, which defaults
+ * execution methods. This class implements the {@code submit},
+ * {@code invokeAny} and {@code invokeAll} methods using a
+ * {@link RunnableFuture} returned by {@code newTaskFor}, which defaults
* to the {@link FutureTask} class provided in this package. For example,
- * the implementation of <tt>submit(Runnable)</tt> creates an
- * associated <tt>RunnableFuture</tt> that is executed and
- * returned. Subclasses may override the <tt>newTaskFor</tt> methods
- * to return <tt>RunnableFuture</tt> implementations other than
- * <tt>FutureTask</tt>.
+ * the implementation of {@code submit(Runnable)} creates an
+ * associated {@code RunnableFuture} that is executed and
+ * returned. Subclasses may override the {@code newTaskFor} methods
+ * to return {@code RunnableFuture} implementations other than
+ * {@code FutureTask}.
*
- * <p> <b>Extension example</b>. Here is a sketch of a class
+ * <p><b>Extension example</b>. Here is a sketch of a class
* that customizes {@link ThreadPoolExecutor} to use
- * a <tt>CustomTask</tt> class instead of the default <tt>FutureTask</tt>:
+ * a {@code CustomTask} class instead of the default {@code FutureTask}:
* <pre> {@code
* public class CustomThreadPoolExecutor extends ThreadPoolExecutor {
*
@@ -42,15 +42,15 @@
public abstract class AbstractExecutorService implements ExecutorService {
/**
- * Returns a <tt>RunnableFuture</tt> for the given runnable and default
+ * Returns a {@code RunnableFuture} for the given runnable and default
* value.
*
* @param runnable the runnable task being wrapped
* @param value the default value for the returned future
- * @return a <tt>RunnableFuture</tt> which when run will run the
- * underlying runnable and which, as a <tt>Future</tt>, will yield
+ * @return a {@code RunnableFuture} which, when run, will run the
+ * underlying runnable and which, as a {@code Future}, will yield
* the given value as its result and provide for cancellation of
- * the underlying task.
+ * the underlying task
* @since 1.6
*/
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
@@ -58,13 +58,13 @@
}
/**
- * Returns a <tt>RunnableFuture</tt> for the given callable task.
+ * Returns a {@code RunnableFuture} for the given callable task.
*
* @param callable the callable task being wrapped
- * @return a <tt>RunnableFuture</tt> which when run will call the
- * underlying callable and which, as a <tt>Future</tt>, will yield
+ * @return a {@code RunnableFuture} which, when run, will call the
+ * underlying callable and which, as a {@code Future}, will yield
* the callable's result as its result and provide for
- * cancellation of the underlying task.
+ * cancellation of the underlying task
* @since 1.6
*/
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
@@ -108,14 +108,14 @@
* the main mechanics of invokeAny.
*/
private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
- boolean timed, long nanos)
+ boolean timed, long nanos)
throws InterruptedException, ExecutionException, TimeoutException {
if (tasks == null)
throw new NullPointerException();
int ntasks = tasks.size();
if (ntasks == 0)
throw new IllegalArgumentException();
- List<Future<T>> futures= new ArrayList<Future<T>>(ntasks);
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
ExecutorCompletionService<T> ecs =
new ExecutorCompletionService<T>(this);
@@ -129,7 +129,7 @@
// Record exceptions so that if we fail to obtain any
// result, we can throw the last exception we got.
ExecutionException ee = null;
- long lastTime = timed ? System.nanoTime() : 0;
+ final long deadline = timed ? System.nanoTime() + nanos : 0L;
Iterator<? extends Callable<T>> it = tasks.iterator();
// Start one task for sure; the rest incrementally
@@ -151,9 +151,7 @@
f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
if (f == null)
throw new TimeoutException();
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
+ nanos = deadline - System.nanoTime();
}
else
f = ecs.take();
@@ -175,8 +173,8 @@
throw ee;
} finally {
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
@@ -200,7 +198,7 @@
throws InterruptedException {
if (tasks == null)
throw new NullPointerException();
- List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks) {
@@ -208,7 +206,8 @@
futures.add(f);
execute(f);
}
- for (Future<T> f : futures) {
+ for (int i = 0, size = futures.size(); i < size; i++) {
+ Future<T> f = futures.get(i);
if (!f.isDone()) {
try {
f.get();
@@ -221,40 +220,39 @@
return futures;
} finally {
if (!done)
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
- if (tasks == null || unit == null)
+ if (tasks == null)
throw new NullPointerException();
long nanos = unit.toNanos(timeout);
- List<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
boolean done = false;
try {
for (Callable<T> t : tasks)
futures.add(newTaskFor(t));
- long lastTime = System.nanoTime();
+ final long deadline = System.nanoTime() + nanos;
+ final int size = futures.size();
// Interleave time checks and calls to execute in case
// executor doesn't have any/much parallelism.
- Iterator<Future<T>> it = futures.iterator();
- while (it.hasNext()) {
- execute((Runnable)(it.next()));
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
- if (nanos <= 0)
+ for (int i = 0; i < size; i++) {
+ execute((Runnable)futures.get(i));
+ nanos = deadline - System.nanoTime();
+ if (nanos <= 0L)
return futures;
}
- for (Future<T> f : futures) {
+ for (int i = 0; i < size; i++) {
+ Future<T> f = futures.get(i);
if (!f.isDone()) {
- if (nanos <= 0)
+ if (nanos <= 0L)
return futures;
try {
f.get(nanos, TimeUnit.NANOSECONDS);
@@ -263,17 +261,15 @@
} catch (TimeoutException toe) {
return futures;
}
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
+ nanos = deadline - System.nanoTime();
}
}
done = true;
return futures;
} finally {
if (!done)
- for (Future<T> f : futures)
- f.cancel(true);
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(true);
}
}
diff --git a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
index e30ab67..3cfe6d5 100644
--- a/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ArrayBlockingQueue.java
@@ -111,9 +111,9 @@
/**
* Returns item at index i.
*/
+ @SuppressWarnings("unchecked")
final E itemAt(int i) {
- @SuppressWarnings("unchecked") E x = (E) items[i];
- return x;
+ return (E) items[i];
}
/**
@@ -147,7 +147,8 @@
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
- @SuppressWarnings("unchecked") E x = (E) items[takeIndex];
+ @SuppressWarnings("unchecked")
+ E x = (E) items[takeIndex];
items[takeIndex] = null;
takeIndex = inc(takeIndex);
count--;
@@ -396,7 +397,7 @@
final ReentrantLock lock = this.lock;
lock.lock();
try {
- return (count == 0) ? null : itemAt(takeIndex);
+ return itemAt(takeIndex); // null when queue is empty
} finally {
lock.unlock();
}
@@ -529,8 +530,13 @@
try {
final int count = this.count;
Object[] a = new Object[count];
- for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
- a[k] = items[i];
+ int n = items.length - takeIndex;
+ if (count <= n) {
+ System.arraycopy(items, takeIndex, a, 0, count);
+ } else {
+ System.arraycopy(items, takeIndex, a, 0, n);
+ System.arraycopy(items, 0, a, n, count - n);
+ }
return a;
} finally {
lock.unlock();
@@ -583,8 +589,13 @@
if (len < count)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), count);
- for (int i = takeIndex, k = 0; k < count; i = inc(i), k++)
- a[k] = (T) items[i];
+ int n = items.length - takeIndex;
+ if (count <= n)
+ System.arraycopy(items, takeIndex, a, 0, count);
+ else {
+ System.arraycopy(items, takeIndex, a, 0, n);
+ System.arraycopy(items, 0, a, n, count - n);
+ }
if (len > count)
a[count] = null;
return a;
@@ -674,7 +685,8 @@
int i = 0;
try {
while (i < n) {
- @SuppressWarnings("unchecked") E x = (E) items[take];
+ @SuppressWarnings("unchecked")
+ E x = (E) items[take];
c.add(x);
items[take] = null;
take = inc(take);
diff --git a/luni/src/main/java/java/util/concurrent/BlockingDeque.java b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
index 34f103d..8a393ba 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingDeque.java
@@ -12,11 +12,11 @@
* for the deque to become non-empty when retrieving an element, and wait for
* space to become available in the deque when storing an element.
*
- * <p><tt>BlockingDeque</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingDeque} methods come in four forms, with different ways
* of handling operations that cannot be satisfied immediately, but may be
* satisfied at some point in the future:
* one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
* blocks the current thread indefinitely until the operation can succeed,
* and the fourth blocks for only a given maximum time limit before giving
* up. These methods are summarized in the following table:
@@ -87,20 +87,20 @@
* </tr>
* </table>
*
- * <p>Like any {@link BlockingQueue}, a <tt>BlockingDeque</tt> is thread safe,
+ * <p>Like any {@link BlockingQueue}, a {@code BlockingDeque} is thread safe,
* does not permit null elements, and may (or may not) be
* capacity-constrained.
*
- * <p>A <tt>BlockingDeque</tt> implementation may be used directly as a FIFO
- * <tt>BlockingQueue</tt>. The methods inherited from the
- * <tt>BlockingQueue</tt> interface are precisely equivalent to
- * <tt>BlockingDeque</tt> methods as indicated in the following table:
+ * <p>A {@code BlockingDeque} implementation may be used directly as a FIFO
+ * {@code BlockingQueue}. The methods inherited from the
+ * {@code BlockingQueue} interface are precisely equivalent to
+ * {@code BlockingDeque} methods as indicated in the following table:
*
* <p>
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <tr>
- * <td ALIGN=CENTER> <b><tt>BlockingQueue</tt> Method</b></td>
- * <td ALIGN=CENTER> <b>Equivalent <tt>BlockingDeque</tt> Method</b></td>
+ * <td ALIGN=CENTER> <b>{@code BlockingQueue} Method</b></td>
+ * <td ALIGN=CENTER> <b>Equivalent {@code BlockingDeque} Method</b></td>
* </tr>
* <tr>
* <td ALIGN=CENTER COLSPAN = 2> <b>Insert</b></td>
@@ -179,7 +179,7 @@
/**
* Inserts the specified element at the front of this deque if it is
* possible to do so immediately without violating capacity restrictions,
- * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * throwing an {@code IllegalStateException} if no space is currently
* available. When using a capacity-restricted deque, it is generally
* preferable to use {@link #offerFirst(Object) offerFirst}.
*
@@ -194,7 +194,7 @@
/**
* Inserts the specified element at the end of this deque if it is
* possible to do so immediately without violating capacity restrictions,
- * throwing an <tt>IllegalStateException</tt> if no space is currently
+ * throwing an {@code IllegalStateException} if no space is currently
* available. When using a capacity-restricted deque, it is generally
* preferable to use {@link #offerLast(Object) offerLast}.
*
@@ -209,7 +209,7 @@
/**
* Inserts the specified element at the front of this deque if it is
* possible to do so immediately without violating capacity restrictions,
- * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * returning {@code true} upon success and {@code false} if no space is
* currently available.
* When using a capacity-restricted deque, this method is generally
* preferable to the {@link #addFirst(Object) addFirst} method, which can
@@ -225,7 +225,7 @@
/**
* Inserts the specified element at the end of this deque if it is
* possible to do so immediately without violating capacity restrictions,
- * returning <tt>true</tt> upon success and <tt>false</tt> if no space is
+ * returning {@code true} upon success and {@code false} if no space is
* currently available.
* When using a capacity-restricted deque, this method is generally
* preferable to the {@link #addLast(Object) addLast} method, which can
@@ -273,10 +273,10 @@
*
* @param e the element to add
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available
* @throws InterruptedException if interrupted while waiting
* @throws ClassCastException if the class of the specified element
@@ -295,10 +295,10 @@
*
* @param e the element to add
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available
* @throws InterruptedException if interrupted while waiting
* @throws ClassCastException if the class of the specified element
@@ -334,10 +334,10 @@
* become available.
*
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return the head of this deque, or <tt>null</tt> if the specified
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return the head of this deque, or {@code null} if the specified
* waiting time elapses before an element is available
* @throws InterruptedException if interrupted while waiting
*/
@@ -350,10 +350,10 @@
* become available.
*
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return the tail of this deque, or <tt>null</tt> if the specified
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return the tail of this deque, or {@code null} if the specified
* waiting time elapses before an element is available
* @throws InterruptedException if interrupted while waiting
*/
@@ -363,13 +363,13 @@
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
- * More formally, removes the first element <tt>e</tt> such that
- * <tt>o.equals(e)</tt> (if such an element exists).
- * Returns <tt>true</tt> if this deque contained the specified element
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
- * @return <tt>true</tt> if an element was removed as a result of this call
+ * @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -381,13 +381,13 @@
/**
* Removes the last occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
- * More formally, removes the last element <tt>e</tt> such that
- * <tt>o.equals(e)</tt> (if such an element exists).
- * Returns <tt>true</tt> if this deque contained the specified element
+ * More formally, removes the last element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* @param o element to be removed from this deque, if present
- * @return <tt>true</tt> if an element was removed as a result of this call
+ * @return {@code true} if an element was removed as a result of this call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -402,8 +402,8 @@
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
- * <tt>true</tt> upon success and throwing an
- * <tt>IllegalStateException</tt> if no space is currently available.
+ * {@code true} upon success and throwing an
+ * {@code IllegalStateException} if no space is currently available.
* When using a capacity-restricted deque, it is generally preferable to
* use {@link #offer(Object) offer}.
*
@@ -423,7 +423,7 @@
* Inserts the specified element into the queue represented by this deque
* (in other words, at the tail of this deque) if it is possible to do so
* immediately without violating capacity restrictions, returning
- * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * {@code true} upon success and {@code false} if no space is currently
* available. When using a capacity-restricted deque, this method is
* generally preferable to the {@link #add} method, which can fail to
* insert an element only by throwing an exception.
@@ -465,8 +465,8 @@
* {@link #offerLast(Object,long,TimeUnit) offerLast}.
*
* @param e the element to add
- * @return <tt>true</tt> if the element was added to this deque, else
- * <tt>false</tt>
+ * @return {@code true} if the element was added to this deque, else
+ * {@code false}
* @throws InterruptedException {@inheritDoc}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this deque
@@ -493,11 +493,11 @@
/**
* Retrieves and removes the head of the queue represented by this deque
* (in other words, the first element of this deque), or returns
- * <tt>null</tt> if this deque is empty.
+ * {@code null} if this deque is empty.
*
* <p>This method is equivalent to {@link #pollFirst()}.
*
- * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ * @return the head of this deque, or {@code null} if this deque is empty
*/
E poll();
@@ -521,7 +521,7 @@
* <p>This method is equivalent to
* {@link #pollFirst(long,TimeUnit) pollFirst}.
*
- * @return the head of this deque, or <tt>null</tt> if the
+ * @return the head of this deque, or {@code null} if the
* specified waiting time elapses before an element is available
* @throws InterruptedException if interrupted while waiting
*/
@@ -544,27 +544,27 @@
/**
* Retrieves, but does not remove, the head of the queue represented by
* this deque (in other words, the first element of this deque), or
- * returns <tt>null</tt> if this deque is empty.
+ * returns {@code null} if this deque is empty.
*
* <p>This method is equivalent to {@link #peekFirst() peekFirst}.
*
- * @return the head of this deque, or <tt>null</tt> if this deque is empty
+ * @return the head of this deque, or {@code null} if this deque is empty
*/
E peek();
/**
* Removes the first occurrence of the specified element from this deque.
* If the deque does not contain the element, it is unchanged.
- * More formally, removes the first element <tt>e</tt> such that
- * <tt>o.equals(e)</tt> (if such an element exists).
- * Returns <tt>true</tt> if this deque contained the specified element
+ * More formally, removes the first element {@code e} such that
+ * {@code o.equals(e)} (if such an element exists).
+ * Returns {@code true} if this deque contained the specified element
* (or equivalently, if this deque changed as a result of the call).
*
* <p>This method is equivalent to
* {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
*
* @param o element to be removed from this deque, if present
- * @return <tt>true</tt> if this deque changed as a result of the call
+ * @return {@code true} if this deque changed as a result of the call
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -574,12 +574,12 @@
boolean remove(Object o);
/**
- * Returns <tt>true</tt> if this deque contains the specified element.
- * More formally, returns <tt>true</tt> if and only if this deque contains
- * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ * Returns {@code true} if this deque contains the specified element.
+ * More formally, returns {@code true} if and only if this deque contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this deque
- * @return <tt>true</tt> if this deque contains the specified element
+ * @return {@code true} if this deque contains the specified element
* @throws ClassCastException if the class of the specified element
* is incompatible with this deque
* (<a href="../Collection.html#optional-restrictions">optional</a>)
diff --git a/luni/src/main/java/java/util/concurrent/BlockingQueue.java b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
index 6cfe52b..cc6d541 100644
--- a/luni/src/main/java/java/util/concurrent/BlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/BlockingQueue.java
@@ -19,11 +19,11 @@
* element, and wait for space to become available in the queue when
* storing an element.
*
- * <p><tt>BlockingQueue</tt> methods come in four forms, with different ways
+ * <p>{@code BlockingQueue} methods come in four forms, with different ways
* of handling operations that cannot be satisfied immediately, but may be
* satisfied at some point in the future:
* one throws an exception, the second returns a special value (either
- * <tt>null</tt> or <tt>false</tt>, depending on the operation), the third
+ * {@code null} or {@code false}, depending on the operation), the third
* blocks the current thread indefinitely until the operation can succeed,
* and the fourth blocks for only a given maximum time limit before giving
* up. These methods are summarized in the following table:
@@ -60,37 +60,37 @@
* </tr>
* </table>
*
- * <p>A <tt>BlockingQueue</tt> does not accept <tt>null</tt> elements.
- * Implementations throw <tt>NullPointerException</tt> on attempts
- * to <tt>add</tt>, <tt>put</tt> or <tt>offer</tt> a <tt>null</tt>. A
- * <tt>null</tt> is used as a sentinel value to indicate failure of
- * <tt>poll</tt> operations.
+ * <p>A {@code BlockingQueue} does not accept {@code null} elements.
+ * Implementations throw {@code NullPointerException} on attempts
+ * to {@code add}, {@code put} or {@code offer} a {@code null}. A
+ * {@code null} is used as a sentinel value to indicate failure of
+ * {@code poll} operations.
*
- * <p>A <tt>BlockingQueue</tt> may be capacity bounded. At any given
- * time it may have a <tt>remainingCapacity</tt> beyond which no
- * additional elements can be <tt>put</tt> without blocking.
- * A <tt>BlockingQueue</tt> without any intrinsic capacity constraints always
- * reports a remaining capacity of <tt>Integer.MAX_VALUE</tt>.
+ * <p>A {@code BlockingQueue} may be capacity bounded. At any given
+ * time it may have a {@code remainingCapacity} beyond which no
+ * additional elements can be {@code put} without blocking.
+ * A {@code BlockingQueue} without any intrinsic capacity constraints always
+ * reports a remaining capacity of {@code Integer.MAX_VALUE}.
*
- * <p> <tt>BlockingQueue</tt> implementations are designed to be used
+ * <p>{@code BlockingQueue} implementations are designed to be used
* primarily for producer-consumer queues, but additionally support
* the {@link java.util.Collection} interface. So, for example, it is
* possible to remove an arbitrary element from a queue using
- * <tt>remove(x)</tt>. However, such operations are in general
+ * {@code remove(x)}. However, such operations are in general
* <em>not</em> performed very efficiently, and are intended for only
* occasional use, such as when a queued message is cancelled.
*
- * <p> <tt>BlockingQueue</tt> implementations are thread-safe. All
+ * <p>{@code BlockingQueue} implementations are thread-safe. All
* queuing methods achieve their effects atomically using internal
* locks or other forms of concurrency control. However, the
- * <em>bulk</em> Collection operations <tt>addAll</tt>,
- * <tt>containsAll</tt>, <tt>retainAll</tt> and <tt>removeAll</tt> are
+ * <em>bulk</em> Collection operations {@code addAll},
+ * {@code containsAll}, {@code retainAll} and {@code removeAll} are
* <em>not</em> necessarily performed atomically unless specified
* otherwise in an implementation. So it is possible, for example, for
- * <tt>addAll(c)</tt> to fail (throwing an exception) after adding
- * only some of the elements in <tt>c</tt>.
+ * {@code addAll(c)} to fail (throwing an exception) after adding
+ * only some of the elements in {@code c}.
*
- * <p>A <tt>BlockingQueue</tt> does <em>not</em> intrinsically support
+ * <p>A {@code BlockingQueue} does <em>not</em> intrinsically support
* any kind of "close" or "shutdown" operation to
* indicate that no more items will be added. The needs and usage of
* such features tend to be implementation-dependent. For example, a
@@ -100,7 +100,7 @@
*
* <p>
* Usage example, based on a typical producer-consumer scenario.
- * Note that a <tt>BlockingQueue</tt> can safely be used with multiple
+ * Note that a {@code BlockingQueue} can safely be used with multiple
* producers and multiple consumers.
* <pre> {@code
* class Producer implements Runnable {
@@ -152,13 +152,13 @@
/**
* Inserts the specified element into this queue if it is possible to do
* so immediately without violating capacity restrictions, returning
- * <tt>true</tt> upon success and throwing an
- * <tt>IllegalStateException</tt> if no space is currently available.
+ * {@code true} upon success and throwing an
+ * {@code IllegalStateException} if no space is currently available.
* When using a capacity-restricted queue, it is generally preferable to
* use {@link #offer(Object) offer}.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @return {@code true} (as specified by {@link Collection#add})
* @throws IllegalStateException if the element cannot be added at this
* time due to capacity restrictions
* @throws ClassCastException if the class of the specified element
@@ -172,14 +172,14 @@
/**
* Inserts the specified element into this queue if it is possible to do
* so immediately without violating capacity restrictions, returning
- * <tt>true</tt> upon success and <tt>false</tt> if no space is currently
+ * {@code true} upon success and {@code false} if no space is currently
* available. When using a capacity-restricted queue, this method is
* generally preferable to {@link #add}, which can fail to insert an
* element only by throwing an exception.
*
* @param e the element to add
- * @return <tt>true</tt> if the element was added to this queue, else
- * <tt>false</tt>
+ * @return {@code true} if the element was added to this queue, else
+ * {@code false}
* @throws ClassCastException if the class of the specified element
* prevents it from being added to this queue
* @throws NullPointerException if the specified element is null
@@ -208,10 +208,10 @@
*
* @param e the element to add
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return <tt>true</tt> if successful, or <tt>false</tt> if
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return {@code true} if successful, or {@code false} if
* the specified waiting time elapses before space is available
* @throws InterruptedException if interrupted while waiting
* @throws ClassCastException if the class of the specified element
@@ -237,10 +237,10 @@
* specified wait time if necessary for an element to become available.
*
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
- * @return the head of this queue, or <tt>null</tt> if the
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
+ * @return the head of this queue, or {@code null} if the
* specified waiting time elapses before an element is available
* @throws InterruptedException if interrupted while waiting
*/
@@ -250,11 +250,11 @@
/**
* Returns the number of additional elements that this queue can ideally
* (in the absence of memory or resource constraints) accept without
- * blocking, or <tt>Integer.MAX_VALUE</tt> if there is no intrinsic
+ * blocking, or {@code Integer.MAX_VALUE} if there is no intrinsic
* limit.
*
* <p>Note that you <em>cannot</em> always tell if an attempt to insert
- * an element will succeed by inspecting <tt>remainingCapacity</tt>
+ * an element will succeed by inspecting {@code remainingCapacity}
* because it may be the case that another thread is about to
* insert or remove an element.
*
@@ -264,14 +264,14 @@
/**
* Removes a single instance of the specified element from this queue,
- * if it is present. More formally, removes an element <tt>e</tt> such
- * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+ * if it is present. More formally, removes an element {@code e} such
+ * that {@code o.equals(e)}, if this queue contains one or more such
* elements.
- * Returns <tt>true</tt> if this queue contained the specified element
+ * Returns {@code true} if this queue contained the specified element
* (or equivalently, if this queue changed as a result of the call).
*
* @param o element to be removed from this queue, if present
- * @return <tt>true</tt> if this queue changed as a result of the call
+ * @return {@code true} if this queue changed as a result of the call
* @throws ClassCastException if the class of the specified element
* is incompatible with this queue
* (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -281,12 +281,12 @@
boolean remove(Object o);
/**
- * Returns <tt>true</tt> if this queue contains the specified element.
- * More formally, returns <tt>true</tt> if and only if this queue contains
- * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ * Returns {@code true} if this queue contains the specified element.
+ * More formally, returns {@code true} if and only if this queue contains
+ * at least one element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this queue
- * @return <tt>true</tt> if this queue contains the specified element
+ * @return {@code true} if this queue contains the specified element
* @throws ClassCastException if the class of the specified element
* is incompatible with this queue
* (<a href="../Collection.html#optional-restrictions">optional</a>)
@@ -300,10 +300,10 @@
* to the given collection. This operation may be more
* efficient than repeatedly polling this queue. A failure
* encountered while attempting to add elements to
- * collection <tt>c</tt> may result in elements being in neither,
+ * collection {@code c} may result in elements being in neither,
* either or both collections when the associated exception is
* thrown. Attempts to drain a queue to itself result in
- * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * {@code IllegalArgumentException}. Further, the behavior of
* this operation is undefined if the specified collection is
* modified while the operation is in progress.
*
@@ -324,10 +324,10 @@
* Removes at most the given number of available elements from
* this queue and adds them to the given collection. A failure
* encountered while attempting to add elements to
- * collection <tt>c</tt> may result in elements being in neither,
+ * collection {@code c} may result in elements being in neither,
* either or both collections when the associated exception is
* thrown. Attempts to drain a queue to itself result in
- * <tt>IllegalArgumentException</tt>. Further, the behavior of
+ * {@code IllegalArgumentException}. Further, the behavior of
* this operation is undefined if the specified collection is
* modified while the operation is in progress.
*
diff --git a/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java b/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
index 76fae13..9fe707d 100644
--- a/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
+++ b/luni/src/main/java/java/util/concurrent/BrokenBarrierException.java
@@ -15,19 +15,18 @@
*
* @since 1.5
* @author Doug Lea
- *
*/
public class BrokenBarrierException extends Exception {
private static final long serialVersionUID = 7117394618823254244L;
/**
- * Constructs a <tt>BrokenBarrierException</tt> with no specified detail
+ * Constructs a {@code BrokenBarrierException} with no specified detail
* message.
*/
public BrokenBarrierException() {}
/**
- * Constructs a <tt>BrokenBarrierException</tt> with the specified
+ * Constructs a {@code BrokenBarrierException} with the specified
* detail message.
*
* @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/Callable.java b/luni/src/main/java/java/util/concurrent/Callable.java
index 293544b..a3b3883 100644
--- a/luni/src/main/java/java/util/concurrent/Callable.java
+++ b/luni/src/main/java/java/util/concurrent/Callable.java
@@ -9,21 +9,21 @@
/**
* A task that returns a result and may throw an exception.
* Implementors define a single method with no arguments called
- * <tt>call</tt>.
+ * {@code call}.
*
- * <p>The <tt>Callable</tt> interface is similar to {@link
+ * <p>The {@code Callable} interface is similar to {@link
* java.lang.Runnable}, in that both are designed for classes whose
* instances are potentially executed by another thread. A
- * <tt>Runnable</tt>, however, does not return a result and cannot
+ * {@code Runnable}, however, does not return a result and cannot
* throw a checked exception.
*
- * <p> The {@link Executors} class contains utility methods to
- * convert from other common forms to <tt>Callable</tt> classes.
+ * <p>The {@link Executors} class contains utility methods to
+ * convert from other common forms to {@code Callable} classes.
*
* @see Executor
* @since 1.5
* @author Doug Lea
- * @param <V> the result type of method <tt>call</tt>
+ * @param <V> the result type of method {@code call}
*/
public interface Callable<V> {
/**
diff --git a/luni/src/main/java/java/util/concurrent/CancellationException.java b/luni/src/main/java/java/util/concurrent/CancellationException.java
index dc452e4..25ab271 100644
--- a/luni/src/main/java/java/util/concurrent/CancellationException.java
+++ b/luni/src/main/java/java/util/concurrent/CancellationException.java
@@ -18,12 +18,12 @@
private static final long serialVersionUID = -9202173006928992231L;
/**
- * Constructs a <tt>CancellationException</tt> with no detail message.
+ * Constructs a {@code CancellationException} with no detail message.
*/
public CancellationException() {}
/**
- * Constructs a <tt>CancellationException</tt> with the specified detail
+ * Constructs a {@code CancellationException} with the specified detail
* message.
*
* @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/CompletionService.java b/luni/src/main/java/java/util/concurrent/CompletionService.java
index 7b0931c..0607596 100644
--- a/luni/src/main/java/java/util/concurrent/CompletionService.java
+++ b/luni/src/main/java/java/util/concurrent/CompletionService.java
@@ -9,17 +9,17 @@
/**
* A service that decouples the production of new asynchronous tasks
* from the consumption of the results of completed tasks. Producers
- * <tt>submit</tt> tasks for execution. Consumers <tt>take</tt>
+ * {@code submit} tasks for execution. Consumers {@code take}
* completed tasks and process their results in the order they
- * complete. A <tt>CompletionService</tt> can for example be used to
- * manage asynchronous IO, in which tasks that perform reads are
+ * complete. A {@code CompletionService} can for example be used to
+ * manage asynchronous I/O, in which tasks that perform reads are
* submitted in one part of a program or system, and then acted upon
* in a different part of the program when the reads complete,
* possibly in a different order than they were requested.
*
- * <p>Typically, a <tt>CompletionService</tt> relies on a separate
+ * <p>Typically, a {@code CompletionService} relies on a separate
* {@link Executor} to actually execute the tasks, in which case the
- * <tt>CompletionService</tt> only manages an internal completion
+ * {@code CompletionService} only manages an internal completion
* queue. The {@link ExecutorCompletionService} class provides an
* implementation of this approach.
*
@@ -28,7 +28,6 @@
* <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
* actions taken by that task, which in turn <i>happen-before</i>
* actions following a successful return from the corresponding {@code take()}.
- *
*/
public interface CompletionService<V> {
/**
@@ -52,7 +51,7 @@
* @param task the task to submit
* @param result the result to return upon successful completion
* @return a Future representing pending completion of the task,
- * and whose <tt>get()</tt> method will return the given
+ * and whose {@code get()} method will return the given
* result value upon completion
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
@@ -69,13 +68,12 @@
*/
Future<V> take() throws InterruptedException;
-
/**
* Retrieves and removes the Future representing the next
- * completed task or <tt>null</tt> if none are present.
+ * completed task, or {@code null} if none are present.
*
* @return the Future representing the next completed task, or
- * <tt>null</tt> if none are present
+ * {@code null} if none are present
*/
Future<V> poll();
@@ -85,11 +83,11 @@
* time if none are yet present.
*
* @param timeout how long to wait before giving up, in units of
- * <tt>unit</tt>
- * @param unit a <tt>TimeUnit</tt> determining how to interpret the
- * <tt>timeout</tt> parameter
+ * {@code unit}
+ * @param unit a {@code TimeUnit} determining how to interpret the
+ * {@code timeout} parameter
* @return the Future representing the next completed task or
- * <tt>null</tt> if the specified waiting time elapses
+ * {@code null} if the specified waiting time elapses
* before one is present
* @throws InterruptedException if interrupted while waiting
*/
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
index 30adb36..54b53ae 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedDeque.java
@@ -63,7 +63,6 @@
* @author Martin Buchholz
* @param <E> the type of elements held in this collection
*/
-
public class ConcurrentLinkedDeque<E>
extends AbstractCollection<E>
implements Deque<E>, java.io.Serializable {
@@ -790,7 +789,7 @@
* Creates an array list and fills it with elements of this list.
* Used by toArray.
*
- * @return the arrayList
+ * @return the array list
*/
private ArrayList<E> toArrayList() {
ArrayList<E> list = new ArrayList<E>();
@@ -1360,11 +1359,10 @@
}
/**
- * Saves the state to a stream (that is, serializes it).
+ * Saves this deque to a stream (that is, serializes it).
*
* @serialData All of the elements (each an {@code E}) in
* the proper order, followed by a null
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1384,8 +1382,7 @@
}
/**
- * Reconstitutes the instance from a stream (that is, deserializes it).
- * @param s the stream
+ * Reconstitutes this deque from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -1408,7 +1405,6 @@
initHeadTail(h, t);
}
-
private boolean casHead(Node<E> cmp, Node<E> val) {
return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
}
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
index a0a26fd..873f825 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentLinkedQueue.java
@@ -69,7 +69,6 @@
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this collection
- *
*/
public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
implements Queue<E>, java.io.Serializable {
@@ -218,7 +217,6 @@
*/
private transient volatile Node<E> tail;
-
/**
* Creates a {@code ConcurrentLinkedQueue} that is initially empty.
*/
@@ -268,7 +266,7 @@
}
/**
- * Try to CAS head to p. If successful, repoint old head to itself
+ * Tries to CAS head to p. If successful, repoint old head to itself
* as sentinel for succ(), below.
*/
final void updateHead(Node<E> h, Node<E> p) {
@@ -717,11 +715,10 @@
}
/**
- * Saves the state to a stream (that is, serializes it).
+ * Saves this queue to a stream (that is, serializes it).
*
* @serialData All of the elements (each an {@code E}) in
* the proper order, followed by a null
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -741,8 +738,7 @@
}
/**
- * Reconstitutes the instance from a stream (that is, deserializes it).
- * @param s the stream
+ * Reconstitutes this queue from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
index 3405acf..27feeb2 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentMap.java
@@ -13,7 +13,7 @@
/**
* A {@link java.util.Map} providing additional atomic
- * <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
+ * {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
*
* <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
@@ -27,7 +27,7 @@
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*/
-public interface ConcurrentMap<K, V> extends Map<K, V> {
+public interface ConcurrentMap<K,V> extends Map<K,V> {
/**
* If the specified key is not already associated
* with a value, associate it with the given value.
@@ -43,11 +43,11 @@
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
- * <tt>null</tt> if there was no mapping for the key.
- * (A <tt>null</tt> return can also indicate that the map
- * previously associated <tt>null</tt> with the key,
+ * {@code null} if there was no mapping for the key.
+ * (A {@code null} return can also indicate that the map
+ * previously associated {@code null} with the key,
* if the implementation supports null values.)
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
@@ -55,7 +55,6 @@
* and this map does not permit null keys or values
* @throws IllegalArgumentException if some property of the specified key
* or value prevents it from being stored in this map
- *
*/
V putIfAbsent(K key, V value);
@@ -73,8 +72,8 @@
*
* @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key
- * @return <tt>true</tt> if the value was removed
- * @throws UnsupportedOperationException if the <tt>remove</tt> operation
+ * @return {@code true} if the value was removed
+ * @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this map
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
@@ -100,8 +99,8 @@
* @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
- * @return <tt>true</tt> if the value was replaced
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * @return {@code true} if the value was replaced
+ * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of a specified key or value
* prevents it from being stored in this map
@@ -126,11 +125,11 @@
* @param key key with which the specified value is associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
- * <tt>null</tt> if there was no mapping for the key.
- * (A <tt>null</tt> return can also indicate that the map
- * previously associated <tt>null</tt> with the key,
+ * {@code null} if there was no mapping for the key.
+ * (A {@code null} return can also indicate that the map
+ * previously associated {@code null} with the key,
* if the implementation supports null values.)
- * @throws UnsupportedOperationException if the <tt>put</tt> operation
+ * @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
index ea99886..e87fbee 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentNavigableMap.java
@@ -38,7 +38,6 @@
*/
ConcurrentNavigableMap<K,V> headMap(K toKey, boolean inclusive);
-
/**
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
@@ -73,7 +72,7 @@
* reflected in the descending map, and vice-versa.
*
* <p>The returned map has an ordering equivalent to
- * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code m.descendingMap().descendingMap()} returns a
* view of {@code m} essentially equivalent to {@code m}.
*
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
index d0d6f14..803cd49 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListMap.java
@@ -20,8 +20,8 @@
* <p>This class implements a concurrent variant of <a
* href="http://en.wikipedia.org/wiki/Skip_list" target="_top">SkipLists</a>
* providing expected average <i>log(n)</i> time cost for the
- * <tt>containsKey</tt>, <tt>get</tt>, <tt>put</tt> and
- * <tt>remove</tt> operations and their variants. Insertion, removal,
+ * {@code containsKey}, {@code get}, {@code put} and
+ * {@code remove} operations and their variants. Insertion, removal,
* update, and access operations safely execute concurrently by
* multiple threads. Iterators are <i>weakly consistent</i>, returning
* elements reflecting the state of the map at some point at or since
@@ -30,28 +30,28 @@
* other operations. Ascending key ordered views and their iterators
* are faster than descending ones.
*
- * <p>All <tt>Map.Entry</tt> pairs returned by methods in this class
+ * <p>All {@code Map.Entry} pairs returned by methods in this class
* and its views represent snapshots of mappings at the time they were
- * produced. They do <em>not</em> support the <tt>Entry.setValue</tt>
+ * produced. They do <em>not</em> support the {@code Entry.setValue}
* method. (Note however that it is possible to change mappings in the
- * associated map using <tt>put</tt>, <tt>putIfAbsent</tt>, or
- * <tt>replace</tt>, depending on exactly which effect you need.)
+ * associated map using {@code put}, {@code putIfAbsent}, or
+ * {@code replace}, depending on exactly which effect you need.)
*
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
* method is <em>not</em> a constant-time operation. Because of the
* asynchronous nature of these maps, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>putAll</tt>, <tt>equals</tt>,
- * <tt>toArray</tt>, <tt>containsValue</tt>, and <tt>clear</tt> are
+ * Additionally, the bulk operations {@code putAll}, {@code equals},
+ * {@code toArray}, {@code containsValue}, and {@code clear} are
* <em>not</em> guaranteed to be performed atomically. For example, an
- * iterator operating concurrently with a <tt>putAll</tt> operation
+ * iterator operating concurrently with a {@code putAll} operation
* might view only some of the added elements.
*
* <p>This class and its views and iterators implement all of the
* <em>optional</em> methods of the {@link Map} and {@link Iterator}
* interfaces. Like most other concurrent collections, this class does
- * <em>not</em> permit the use of <tt>null</tt> keys or values because some
+ * <em>not</em> permit the use of {@code null} keys or values because some
* null return values cannot be reliably distinguished from the absence of
* elements.
*
@@ -60,6 +60,7 @@
* @param <V> the type of mapped values
* @since 1.6
*/
+@SuppressWarnings("unchecked")
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
implements ConcurrentNavigableMap<K,V>,
Cloneable,
@@ -408,7 +409,7 @@
* because callers will have already read value field and need
* to use that read (not another done here) and so directly
* test if value points to node.
- * @param n a possibly null reference to a node
+ *
* @return true if this node is a marker node
*/
boolean isMarker() {
@@ -457,7 +458,7 @@
* Returns value if this node contains a valid key-value pair,
* else null.
* @return this node's value if it isn't a marker or header or
- * is deleted, else null.
+ * is deleted, else null
*/
V getValidValue() {
Object v = value;
@@ -810,7 +811,7 @@
* Main insertion method. Adds element if not present, or
* replaces value if present and onlyIfAbsent is false.
* @param kkey the key
- * @param value the value that must be associated with key
+ * @param value the value that must be associated with key
* @param onlyIfAbsent if should not insert if already present
* @return the old value, or null if newly inserted
*/
@@ -934,7 +935,7 @@
* Adds given index nodes from given level down to 1.
* @param idx the topmost index node being inserted
* @param h the value of head to use to insert. This must be
- * snapshotted by callers to provide correct insertion level
+ * snapshotted by callers to provide correct insertion level.
* @param indexLevel the level of the index
*/
private void addIndex(Index<K,V> idx, HeadIndex<K,V> h, int indexLevel) {
@@ -1359,7 +1360,7 @@
* comparator.
*
* @param comparator the comparator that will be used to order this map.
- * If <tt>null</tt>, the {@linkplain Comparable natural
+ * If {@code null}, the {@linkplain Comparable natural
* ordering} of the keys will be used.
*/
public ConcurrentSkipListMap(Comparator<? super K> comparator) {
@@ -1373,7 +1374,7 @@
* the keys.
*
* @param m the map whose mappings are to be placed in this map
- * @throws ClassCastException if the keys in <tt>m</tt> are not
+ * @throws ClassCastException if the keys in {@code m} are not
* {@link Comparable}, or are not mutually comparable
* @throws NullPointerException if the specified map or any of its keys
* or values are null
@@ -1400,7 +1401,7 @@
}
/**
- * Returns a shallow copy of this <tt>ConcurrentSkipListMap</tt>
+ * Returns a shallow copy of this {@code ConcurrentSkipListMap}
* instance. (The keys and values themselves are not cloned.)
*
* @return a shallow copy of this map
@@ -1477,11 +1478,11 @@
/* ---------------- Serialization -------------- */
/**
- * Saves the state of this map to a stream (that is, serializes it).
+ * Saves this map to a stream (that is, serializes it).
*
* @serialData The key (Object) and value (Object) for each
* key-value mapping represented by the map, followed by
- * <tt>null</tt>. The key-value mappings are emitted in key-order
+ * {@code null}. The key-value mappings are emitted in key-order
* (as determined by the Comparator, or by the keys' natural
* ordering if no Comparator).
*/
@@ -1502,9 +1503,7 @@
}
/**
- * Reconstitutes the map from a stream (that is, deserializes it).
- *
- * @param s the stream
+ * Reconstitutes this map from a stream (that is, deserializes it).
*/
private void readObject(final java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -1567,11 +1566,11 @@
/* ------ Map API methods ------ */
/**
- * Returns <tt>true</tt> if this map contains a mapping for the specified
+ * Returns {@code true} if this map contains a mapping for the specified
* key.
*
* @param key key whose presence in this map is to be tested
- * @return <tt>true</tt> if this map contains a mapping for the specified key
+ * @return {@code true} if this map contains a mapping for the specified key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
@@ -1606,7 +1605,7 @@
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
- * <tt>null</tt> if there was no mapping for the key
+ * {@code null} if there was no mapping for the key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key or value is null
@@ -1622,7 +1621,7 @@
*
* @param key key for which mapping should be removed
* @return the previous value associated with the specified key, or
- * <tt>null</tt> if there was no mapping for the key
+ * {@code null} if there was no mapping for the key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key is null
@@ -1632,15 +1631,15 @@
}
/**
- * Returns <tt>true</tt> if this map maps one or more keys to the
+ * Returns {@code true} if this map maps one or more keys to the
* specified value. This operation requires time linear in the
* map size. Additionally, it is possible for the map to change
* during execution of this method, in which case the returned
* result may be inaccurate.
*
* @param value value whose presence in this map is to be tested
- * @return <tt>true</tt> if a mapping to <tt>value</tt> exists;
- * <tt>false</tt> otherwise
+ * @return {@code true} if a mapping to {@code value} exists;
+ * {@code false} otherwise
* @throws NullPointerException if the specified value is null
*/
public boolean containsValue(Object value) {
@@ -1656,8 +1655,8 @@
/**
* Returns the number of key-value mappings in this map. If this map
- * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
- * returns <tt>Integer.MAX_VALUE</tt>.
+ * contains more than {@code Integer.MAX_VALUE} elements, it
+ * returns {@code Integer.MAX_VALUE}.
*
* <p>Beware that, unlike in most collections, this method is
* <em>NOT</em> a constant-time operation. Because of the
@@ -1680,8 +1679,8 @@
}
/**
- * Returns <tt>true</tt> if this map contains no key-value mappings.
- * @return <tt>true</tt> if this map contains no key-value mappings
+ * Returns {@code true} if this map contains no key-value mappings.
+ * @return {@code true} if this map contains no key-value mappings
*/
public boolean isEmpty() {
return findFirst() == null;
@@ -1743,12 +1742,12 @@
* The collection is backed by the map, so changes to the map are
* reflected in the collection, and vice-versa. The collection
* supports element removal, which removes the corresponding
- * mapping from the map, via the <tt>Iterator.remove</tt>,
- * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
- * <tt>retainAll</tt> and <tt>clear</tt> operations. It does not
- * support the <tt>add</tt> or <tt>addAll</tt> operations.
+ * mapping from the map, via the {@code Iterator.remove},
+ * {@code Collection.remove}, {@code removeAll},
+ * {@code retainAll} and {@code clear} operations. It does not
+ * support the {@code add} or {@code addAll} operations.
*
- * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
@@ -1765,20 +1764,20 @@
* The set is backed by the map, so changes to the map are
* reflected in the set, and vice-versa. The set supports element
* removal, which removes the corresponding mapping from the map,
- * via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
- * operations. It does not support the <tt>add</tt> or
- * <tt>addAll</tt> operations.
+ * via the {@code Iterator.remove}, {@code Set.remove},
+ * {@code removeAll}, {@code retainAll} and {@code clear}
+ * operations. It does not support the {@code add} or
+ * {@code addAll} operations.
*
- * <p>The view's <tt>iterator</tt> is a "weakly consistent" iterator
+ * <p>The view's {@code iterator} is a "weakly consistent" iterator
* that will never throw {@link ConcurrentModificationException},
* and guarantees to traverse elements as they existed upon
* construction of the iterator, and may (but is not guaranteed to)
* reflect any modifications subsequent to construction.
*
- * <p>The <tt>Map.Entry</tt> elements returned by
- * <tt>iterator.next()</tt> do <em>not</em> support the
- * <tt>setValue</tt> operation.
+ * <p>The {@code Map.Entry} elements returned by
+ * {@code iterator.next()} do <em>not</em> support the
+ * {@code setValue} operation.
*
* @return a set view of the mappings contained in this map,
* sorted in ascending key order
@@ -1802,15 +1801,15 @@
/**
* Compares the specified object with this map for equality.
- * Returns <tt>true</tt> if the given object is also a map and the
+ * Returns {@code true} if the given object is also a map and the
* two maps represent the same mappings. More formally, two maps
- * <tt>m1</tt> and <tt>m2</tt> represent the same mappings if
- * <tt>m1.entrySet().equals(m2.entrySet())</tt>. This
+ * {@code m1} and {@code m2} represent the same mappings if
+ * {@code m1.entrySet().equals(m2.entrySet())}. This
* operation may return misleading results if either map is
* concurrently modified during execution of this method.
*
* @param o object to be compared for equality with this map
- * @return <tt>true</tt> if the specified object is equal to this map
+ * @return {@code true} if the specified object is equal to this map
*/
public boolean equals(Object o) {
if (o == this)
@@ -1842,7 +1841,7 @@
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
- * or <tt>null</tt> if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key or value is null
@@ -1897,7 +1896,7 @@
* {@inheritDoc}
*
* @return the previous value associated with the specified key,
- * or <tt>null</tt> if there was no mapping for the key
+ * or {@code null} if there was no mapping for the key
* @throws ClassCastException if the specified key cannot be compared
* with the keys currently in the map
* @throws NullPointerException if the specified key or value is null
@@ -2014,9 +2013,9 @@
/**
* Returns a key-value mapping associated with the greatest key
- * strictly less than the given key, or <tt>null</tt> if there is
+ * strictly less than the given key, or {@code null} if there is
* no such key. The returned entry does <em>not</em> support the
- * <tt>Entry.setValue</tt> method.
+ * {@code Entry.setValue} method.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
@@ -2036,9 +2035,9 @@
/**
* Returns a key-value mapping associated with the greatest key
- * less than or equal to the given key, or <tt>null</tt> if there
+ * less than or equal to the given key, or {@code null} if there
* is no such key. The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*
* @param key the key
* @throws ClassCastException {@inheritDoc}
@@ -2060,9 +2059,9 @@
/**
* Returns a key-value mapping associated with the least key
- * greater than or equal to the given key, or <tt>null</tt> if
+ * greater than or equal to the given key, or {@code null} if
* there is no such entry. The returned entry does <em>not</em>
- * support the <tt>Entry.setValue</tt> method.
+ * support the {@code Entry.setValue} method.
*
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException if the specified key is null
@@ -2082,9 +2081,9 @@
/**
* Returns a key-value mapping associated with the least key
- * strictly greater than the given key, or <tt>null</tt> if there
+ * strictly greater than the given key, or {@code null} if there
* is no such key. The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*
* @param key the key
* @throws ClassCastException {@inheritDoc}
@@ -2106,9 +2105,9 @@
/**
* Returns a key-value mapping associated with the least
- * key in this map, or <tt>null</tt> if the map is empty.
+ * key in this map, or {@code null} if the map is empty.
* The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*/
public Map.Entry<K,V> firstEntry() {
for (;;) {
@@ -2123,9 +2122,9 @@
/**
* Returns a key-value mapping associated with the greatest
- * key in this map, or <tt>null</tt> if the map is empty.
+ * key in this map, or {@code null} if the map is empty.
* The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*/
public Map.Entry<K,V> lastEntry() {
for (;;) {
@@ -2140,9 +2139,9 @@
/**
* Removes and returns a key-value mapping associated with
- * the least key in this map, or <tt>null</tt> if the map is empty.
+ * the least key in this map, or {@code null} if the map is empty.
* The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*/
public Map.Entry<K,V> pollFirstEntry() {
return doRemoveFirstEntry();
@@ -2150,9 +2149,9 @@
/**
* Removes and returns a key-value mapping associated with
- * the greatest key in this map, or <tt>null</tt> if the map is empty.
+ * the greatest key in this map, or {@code null} if the map is empty.
* The returned entry does <em>not</em> support
- * the <tt>Entry.setValue</tt> method.
+ * the {@code Entry.setValue} method.
*/
public Map.Entry<K,V> pollLastEntry() {
return doRemoveLastEntry();
@@ -2268,7 +2267,7 @@
static final <E> List<E> toList(Collection<E> c) {
// Using size() here would be a pessimization.
- List<E> list = new ArrayList<E>();
+ ArrayList<E> list = new ArrayList<E>();
for (E e : c)
list.add(e);
return list;
@@ -2312,7 +2311,7 @@
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
- } catch (ClassCastException unused) {
+ } catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
@@ -2421,7 +2420,7 @@
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
- } catch (ClassCastException unused) {
+ } catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
@@ -2438,8 +2437,8 @@
* underlying maps, differing in that mappings outside their range are
* ignored, and attempts to add mappings outside their ranges result
* in {@link IllegalArgumentException}. Instances of this class are
- * constructed only using the <tt>subMap</tt>, <tt>headMap</tt>, and
- * <tt>tailMap</tt> methods of their underlying maps.
+ * constructed only using the {@code subMap}, {@code headMap}, and
+ * {@code tailMap} methods of their underlying maps.
*
* @serial include
*/
@@ -2467,7 +2466,7 @@
private transient Collection<V> valuesView;
/**
- * Creates a new submap, initializing all fields
+ * Creates a new submap, initializing all fields.
*/
SubMap(ConcurrentSkipListMap<K,V> map,
K fromKey, boolean fromInclusive,
@@ -2516,7 +2515,7 @@
}
/**
- * Returns true if node key is less than upper bound of range
+ * Returns true if node key is less than upper bound of range.
*/
private boolean isBeforeEnd(ConcurrentSkipListMap.Node<K,V> n) {
if (n == null)
@@ -2534,7 +2533,7 @@
/**
* Returns lowest node. This node might not be in range, so
- * most usages need to check bounds
+ * most usages need to check bounds.
*/
private ConcurrentSkipListMap.Node<K,V> loNode() {
if (lo == null)
@@ -2547,7 +2546,7 @@
/**
* Returns highest node. This node might not be in range, so
- * most usages need to check bounds
+ * most usages need to check bounds.
*/
private ConcurrentSkipListMap.Node<K,V> hiNode() {
if (hi == null)
@@ -2559,7 +2558,7 @@
}
/**
- * Returns lowest absolute key (ignoring directonality)
+ * Returns lowest absolute key (ignoring directonality).
*/
private K lowestKey() {
ConcurrentSkipListMap.Node<K,V> n = loNode();
@@ -2570,7 +2569,7 @@
}
/**
- * Returns highest absolute key (ignoring directonality)
+ * Returns highest absolute key (ignoring directonality).
*/
private K highestKey() {
ConcurrentSkipListMap.Node<K,V> n = hiNode();
diff --git a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
index 71431a9..f1402b6 100644
--- a/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
+++ b/luni/src/main/java/java/util/concurrent/ConcurrentSkipListSet.java
@@ -19,7 +19,7 @@
* on which constructor is used.
*
* <p>This implementation provides expected average <i>log(n)</i> time
- * cost for the <tt>contains</tt>, <tt>add</tt>, and <tt>remove</tt>
+ * cost for the {@code contains}, {@code add}, and {@code remove}
* operations and their variants. Insertion, removal, and access
* operations safely execute concurrently by multiple threads.
* Iterators are <i>weakly consistent</i>, returning elements
@@ -29,23 +29,23 @@
* other operations. Ascending ordered views and their iterators are
* faster than descending ones.
*
- * <p>Beware that, unlike in most collections, the <tt>size</tt>
+ * <p>Beware that, unlike in most collections, the {@code size}
* method is <em>not</em> a constant-time operation. Because of the
* asynchronous nature of these sets, determining the current number
* of elements requires a traversal of the elements, and so may report
* inaccurate results if this collection is modified during traversal.
- * Additionally, the bulk operations <tt>addAll</tt>,
- * <tt>removeAll</tt>, <tt>retainAll</tt>, <tt>containsAll</tt>,
- * <tt>equals</tt>, and <tt>toArray</tt> are <em>not</em> guaranteed
+ * Additionally, the bulk operations {@code addAll},
+ * {@code removeAll}, {@code retainAll}, {@code containsAll},
+ * {@code equals}, and {@code toArray} are <em>not</em> guaranteed
* to be performed atomically. For example, an iterator operating
- * concurrently with an <tt>addAll</tt> operation might view only some
+ * concurrently with an {@code addAll} operation might view only some
* of the added elements.
*
* <p>This class and its iterators implement all of the
* <em>optional</em> methods of the {@link Set} and {@link Iterator}
* interfaces. Like most other concurrent collection implementations,
- * this class does not permit the use of <tt>null</tt> elements,
- * because <tt>null</tt> arguments and return values cannot be reliably
+ * this class does not permit the use of {@code null} elements,
+ * because {@code null} arguments and return values cannot be reliably
* distinguished from the absence of elements.
*
* @author Doug Lea
@@ -61,7 +61,7 @@
/**
* The underlying map. Uses Boolean.TRUE as value for each
* element. This field is declared final for the sake of thread
- * safety, which entails some ugliness in clone()
+ * safety, which entails some ugliness in clone().
*/
private final ConcurrentNavigableMap<E,Object> m;
@@ -78,7 +78,7 @@
* the specified comparator.
*
* @param comparator the comparator that will be used to order this set.
- * If <tt>null</tt>, the {@linkplain Comparable natural
+ * If {@code null}, the {@linkplain Comparable natural
* ordering} of the elements will be used.
*/
public ConcurrentSkipListSet(Comparator<? super E> comparator) {
@@ -91,7 +91,7 @@
* {@linkplain Comparable natural ordering}.
*
* @param c The elements that will comprise the new set
- * @throws ClassCastException if the elements in <tt>c</tt> are
+ * @throws ClassCastException if the elements in {@code c} are
* not {@link Comparable}, or are not mutually comparable
* @throws NullPointerException if the specified collection or any
* of its elements are null
@@ -122,7 +122,7 @@
}
/**
- * Returns a shallow copy of this <tt>ConcurrentSkipListSet</tt>
+ * Returns a shallow copy of this {@code ConcurrentSkipListSet}
* instance. (The elements themselves are not cloned.)
*
* @return a shallow copy of this set
@@ -143,8 +143,8 @@
/**
* Returns the number of elements in this set. If this set
- * contains more than <tt>Integer.MAX_VALUE</tt> elements, it
- * returns <tt>Integer.MAX_VALUE</tt>.
+ * contains more than {@code Integer.MAX_VALUE} elements, it
+ * returns {@code Integer.MAX_VALUE}.
*
* <p>Beware that, unlike in most collections, this method is
* <em>NOT</em> a constant-time operation. Because of the
@@ -162,20 +162,20 @@
}
/**
- * Returns <tt>true</tt> if this set contains no elements.
- * @return <tt>true</tt> if this set contains no elements
+ * Returns {@code true} if this set contains no elements.
+ * @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return m.isEmpty();
}
/**
- * Returns <tt>true</tt> if this set contains the specified element.
- * More formally, returns <tt>true</tt> if and only if this set
- * contains an element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+ * Returns {@code true} if this set contains the specified element.
+ * More formally, returns {@code true} if and only if this set
+ * contains an element {@code e} such that {@code o.equals(e)}.
*
* @param o object to be checked for containment in this set
- * @return <tt>true</tt> if this set contains the specified element
+ * @return {@code true} if this set contains the specified element
* @throws ClassCastException if the specified element cannot be
* compared with the elements currently in this set
* @throws NullPointerException if the specified element is null
@@ -186,15 +186,15 @@
/**
* Adds the specified element to this set if it is not already present.
- * More formally, adds the specified element <tt>e</tt> to this set if
- * the set contains no element <tt>e2</tt> such that <tt>e.equals(e2)</tt>.
+ * More formally, adds the specified element {@code e} to this set if
+ * the set contains no element {@code e2} such that {@code e.equals(e2)}.
* If this set already contains the element, the call leaves the set
- * unchanged and returns <tt>false</tt>.
+ * unchanged and returns {@code false}.
*
* @param e element to be added to this set
- * @return <tt>true</tt> if this set did not already contain the
+ * @return {@code true} if this set did not already contain the
* specified element
- * @throws ClassCastException if <tt>e</tt> cannot be compared
+ * @throws ClassCastException if {@code e} cannot be compared
* with the elements currently in this set
* @throws NullPointerException if the specified element is null
*/
@@ -204,15 +204,15 @@
/**
* Removes the specified element from this set if it is present.
- * More formally, removes an element <tt>e</tt> such that
- * <tt>o.equals(e)</tt>, if this set contains such an element.
- * Returns <tt>true</tt> if this set contained the element (or
+ * More formally, removes an element {@code e} such that
+ * {@code o.equals(e)}, if this set contains such an element.
+ * Returns {@code true} if this set contained the element (or
* equivalently, if this set changed as a result of the call).
* (This set will not contain the element once the call returns.)
*
* @param o object to be removed from this set, if present
- * @return <tt>true</tt> if this set contained the specified element
- * @throws ClassCastException if <tt>o</tt> cannot be compared
+ * @return {@code true} if this set contained the specified element
+ * @throws ClassCastException if {@code o} cannot be compared
* with the elements currently in this set
* @throws NullPointerException if the specified element is null
*/
@@ -250,7 +250,7 @@
/**
* Compares the specified object with this set for equality. Returns
- * <tt>true</tt> if the specified object is also a set, the two sets
+ * {@code true} if the specified object is also a set, the two sets
* have the same size, and every member of the specified set is
* contained in this set (or equivalently, every member of this set is
* contained in the specified set). This definition ensures that the
@@ -258,7 +258,7 @@
* set interface.
*
* @param o the object to be compared for equality with this set
- * @return <tt>true</tt> if the specified object is equal to this set
+ * @return {@code true} if the specified object is equal to this set
*/
public boolean equals(Object o) {
// Override AbstractSet version to avoid calling size()
@@ -269,7 +269,7 @@
Collection<?> c = (Collection<?>) o;
try {
return containsAll(c) && c.containsAll(this);
- } catch (ClassCastException unused) {
+ } catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
@@ -283,7 +283,7 @@
* value is the <i>asymmetric set difference</i> of the two sets.
*
* @param c collection containing elements to be removed from this set
- * @return <tt>true</tt> if this set changed as a result of the call
+ * @return {@code true} if this set changed as a result of the call
* @throws ClassCastException if the types of one or more elements in this
* set are incompatible with the specified collection
* @throws NullPointerException if the specified collection or any
@@ -431,7 +431,7 @@
* reflected in the descending set, and vice-versa.
*
* <p>The returned set has an ordering equivalent to
- * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
+ * {@link Collections#reverseOrder(Comparator) Collections.reverseOrder}{@code (comparator())}.
* The expression {@code s.descendingSet().descendingSet()} returns a
* view of {@code s} essentially equivalent to {@code s}.
*
diff --git a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
index 1f37bc9..6fa8feb 100644
--- a/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
+++ b/luni/src/main/java/java/util/concurrent/CopyOnWriteArraySet.java
@@ -20,17 +20,17 @@
* vastly outnumber mutative operations, and you need
* to prevent interference among threads during traversal.
* <li>It is thread-safe.
- * <li>Mutative operations (<tt>add</tt>, <tt>set</tt>, <tt>remove</tt>, etc.)
+ * <li>Mutative operations ({@code add}, {@code set}, {@code remove}, etc.)
* are expensive since they usually entail copying the entire underlying
* array.
- * <li>Iterators do not support the mutative <tt>remove</tt> operation.
+ * <li>Iterators do not support the mutative {@code remove} operation.
* <li>Traversal via iterators is fast and cannot encounter
* interference from other threads. Iterators rely on
* unchanging snapshots of the array at the time the iterators were
* constructed.
* </ul>
*
- * <p> <b>Sample Usage.</b> The following code sketch uses a
+ * <p><b>Sample Usage.</b> The following code sketch uses a
* copy-on-write set to maintain a set of Handler objects that
* perform some action upon state updates.
*
@@ -48,7 +48,7 @@
* public void update() {
* changeState();
* for (Handler handler : handlers)
- * handler.handle();
+ * handler.handle();
* }
* }}</pre>
*
@@ -92,22 +92,22 @@
}
/**
- * Returns <tt>true</tt> if this set contains no elements.
+ * Returns {@code true} if this set contains no elements.
*
- * @return <tt>true</tt> if this set contains no elements
+ * @return {@code true} if this set contains no elements
*/
public boolean isEmpty() {
return al.isEmpty();
}
/**
- * Returns <tt>true</tt> if this set contains the specified element.
- * More formally, returns <tt>true</tt> if and only if this set
- * contains an element <tt>e</tt> such that
+ * Returns {@code true} if this set contains the specified element.
+ * More formally, returns {@code true} if and only if this set
+ * contains an element {@code e} such that
* <tt>(o==null ? e==null : o.equals(e))</tt>.
*
* @param o element whose presence in this set is to be tested
- * @return <tt>true</tt> if this set contains the specified element
+ * @return {@code true} if this set contains the specified element
*/
public boolean contains(Object o) {
return al.contains(o);
@@ -143,7 +143,7 @@
* <p>If this set fits in the specified array with room to spare
* (i.e., the array has more elements than this set), the element in
* the array immediately following the end of the set is set to
- * <tt>null</tt>. (This is useful in determining the length of this
+ * {@code null}. (This is useful in determining the length of this
* set <i>only</i> if the caller knows that this set does not contain
* any null elements.)
*
@@ -156,14 +156,14 @@
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
- * <p>Suppose <tt>x</tt> is a set known to contain only strings.
+ * <p>Suppose {@code x} is a set known to contain only strings.
* The following code can be used to dump the set into a newly allocated
- * array of <tt>String</tt>:
+ * array of {@code String}:
*
* <pre> {@code String[] y = x.toArray(new String[0]);}</pre>
*
- * Note that <tt>toArray(new Object[0])</tt> is identical in function to
- * <tt>toArray()</tt>.
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
*
* @param a the array into which the elements of this set are to be
* stored, if it is big enough; otherwise, a new array of the same
@@ -188,15 +188,15 @@
/**
* Removes the specified element from this set if it is present.
- * More formally, removes an element <tt>e</tt> such that
+ * More formally, removes an element {@code e} such that
* <tt>(o==null ? e==null : o.equals(e))</tt>,
- * if this set contains such an element. Returns <tt>true</tt> if
+ * if this set contains such an element. Returns {@code true} if
* this set contained the element (or equivalently, if this set
* changed as a result of the call). (This set will not contain the
* element once the call returns.)
*
* @param o object to be removed from this set, if present
- * @return <tt>true</tt> if this set contained the specified element
+ * @return {@code true} if this set contained the specified element
*/
public boolean remove(Object o) {
return al.remove(o);
@@ -204,14 +204,14 @@
/**
* Adds the specified element to this set if it is not already present.
- * More formally, adds the specified element <tt>e</tt> to this set if
- * the set contains no element <tt>e2</tt> such that
+ * More formally, adds the specified element {@code e} to this set if
+ * the set contains no element {@code e2} such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
- * unchanged and returns <tt>false</tt>.
+ * unchanged and returns {@code false}.
*
* @param e element to be added to this set
- * @return <tt>true</tt> if this set did not already contain the specified
+ * @return {@code true} if this set did not already contain the specified
* element
*/
public boolean add(E e) {
@@ -219,12 +219,12 @@
}
/**
- * Returns <tt>true</tt> if this set contains all of the elements of the
+ * Returns {@code true} if this set contains all of the elements of the
* specified collection. If the specified collection is also a set, this
- * method returns <tt>true</tt> if it is a <i>subset</i> of this set.
+ * method returns {@code true} if it is a <i>subset</i> of this set.
*
* @param c collection to be checked for containment in this set
- * @return <tt>true</tt> if this set contains all of the elements of the
+ * @return {@code true} if this set contains all of the elements of the
* specified collection
* @throws NullPointerException if the specified collection is null
* @see #contains(Object)
@@ -236,13 +236,13 @@
/**
* Adds all of the elements in the specified collection to this set if
* they're not already present. If the specified collection is also a
- * set, the <tt>addAll</tt> operation effectively modifies this set so
+ * set, the {@code addAll} operation effectively modifies this set so
* that its value is the <i>union</i> of the two sets. The behavior of
* this operation is undefined if the specified collection is modified
* while the operation is in progress.
*
* @param c collection containing elements to be added to this set
- * @return <tt>true</tt> if this set changed as a result of the call
+ * @return {@code true} if this set changed as a result of the call
* @throws NullPointerException if the specified collection is null
* @see #add(Object)
*/
@@ -257,7 +257,7 @@
* <i>asymmetric set difference</i> of the two sets.
*
* @param c collection containing elements to be removed from this set
- * @return <tt>true</tt> if this set changed as a result of the call
+ * @return {@code true} if this set changed as a result of the call
* @throws ClassCastException if the class of an element of this set
* is incompatible with the specified collection (optional)
* @throws NullPointerException if this set contains a null element and the
@@ -278,7 +278,7 @@
* two sets.
*
* @param c collection containing elements to be retained in this set
- * @return <tt>true</tt> if this set changed as a result of the call
+ * @return {@code true} if this set changed as a result of the call
* @throws ClassCastException if the class of an element of this set
* is incompatible with the specified collection (optional)
* @throws NullPointerException if this set contains a null element and the
@@ -297,7 +297,7 @@
* <p>The returned iterator provides a snapshot of the state of the set
* when the iterator was constructed. No synchronization is needed while
* traversing the iterator. The iterator does <em>NOT</em> support the
- * <tt>remove</tt> method.
+ * {@code remove} method.
*
* @return an iterator over the elements in this set
*/
@@ -354,7 +354,7 @@
}
/**
- * Test for equality, coping with nulls.
+ * Tests for equality, coping with nulls.
*/
private static boolean eq(Object o1, Object o2) {
return (o1 == null) ? o2 == null : o1.equals(o2);
diff --git a/luni/src/main/java/java/util/concurrent/CountDownLatch.java b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
index e90badf..fe0fa65 100644
--- a/luni/src/main/java/java/util/concurrent/CountDownLatch.java
+++ b/luni/src/main/java/java/util/concurrent/CountDownLatch.java
@@ -5,7 +5,7 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* A synchronization aid that allows one or more threads to wait until
@@ -63,15 +63,15 @@
* private final CountDownLatch startSignal;
* private final CountDownLatch doneSignal;
* Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {
- * this.startSignal = startSignal;
- * this.doneSignal = doneSignal;
+ * this.startSignal = startSignal;
+ * this.doneSignal = doneSignal;
* }
* public void run() {
- * try {
- * startSignal.await();
- * doWork();
- * doneSignal.countDown();
- * } catch (InterruptedException ex) {} // return;
+ * try {
+ * startSignal.await();
+ * doWork();
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
* }
*
* void doWork() { ... }
@@ -101,14 +101,14 @@
* private final CountDownLatch doneSignal;
* private final int i;
* WorkerRunnable(CountDownLatch doneSignal, int i) {
- * this.doneSignal = doneSignal;
- * this.i = i;
+ * this.doneSignal = doneSignal;
+ * this.i = i;
* }
* public void run() {
- * try {
- * doWork(i);
- * doneSignal.countDown();
- * } catch (InterruptedException ex) {} // return;
+ * try {
+ * doWork(i);
+ * doneSignal.countDown();
+ * } catch (InterruptedException ex) {} // return;
* }
*
* void doWork() { ... }
diff --git a/luni/src/main/java/java/util/concurrent/CountedCompleter.java b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
new file mode 100644
index 0000000..ffe7582
--- /dev/null
+++ b/luni/src/main/java/java/util/concurrent/CountedCompleter.java
@@ -0,0 +1,715 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+package java.util.concurrent;
+
+/**
+ * A {@link ForkJoinTask} with a completion action performed when
+ * triggered and there are no remaining pending
+ * actions. CountedCompleters are in general more robust in the
+ * presence of subtask stalls and blockage than are other forms of
+ * ForkJoinTasks, but are less intuitive to program. Uses of
+ * CountedCompleter are similar to those of other completion based
+ * components (such as {@link java.nio.channels.CompletionHandler})
+ * except that multiple <em>pending</em> completions may be necessary
+ * to trigger the completion action {@link #onCompletion}, not just one.
+ * Unless initialized otherwise, the {@linkplain #getPendingCount pending
+ * count} starts at zero, but may be (atomically) changed using
+ * methods {@link #setPendingCount}, {@link #addToPendingCount}, and
+ * {@link #compareAndSetPendingCount}. Upon invocation of {@link
+ * #tryComplete}, if the pending action count is nonzero, it is
+ * decremented; otherwise, the completion action is performed, and if
+ * this completer itself has a completer, the process is continued
+ * with its completer. As is the case with related synchronization
+ * components such as {@link java.util.concurrent.Phaser Phaser} and
+ * {@link java.util.concurrent.Semaphore Semaphore}, these methods
+ * affect only internal counts; they do not establish any further
+ * internal bookkeeping. In particular, the identities of pending
+ * tasks are not maintained. As illustrated below, you can create
+ * subclasses that do record some or all pending tasks or their
+ * results when needed. As illustrated below, utility methods
+ * supporting customization of completion traversals are also
+ * provided. However, because CountedCompleters provide only basic
+ * synchronization mechanisms, it may be useful to create further
+ * abstract subclasses that maintain linkages, fields, and additional
+ * support methods appropriate for a set of related usages.
+ *
+ * <p>A concrete CountedCompleter class must define method {@link
+ * #compute}, that should in most cases (as illustrated below), invoke
+ * {@code tryComplete()} once before returning. The class may also
+ * optionally override method {@link #onCompletion} to perform an
+ * action upon normal completion, and method {@link
+ * #onExceptionalCompletion} to perform an action upon any exception.
+ *
+ * <p>CountedCompleters most often do not bear results, in which case
+ * they are normally declared as {@code CountedCompleter<Void>}, and
+ * will always return {@code null} as a result value. In other cases,
+ * you should override method {@link #getRawResult} to provide a
+ * result from {@code join(), invoke()}, and related methods. In
+ * general, this method should return the value of a field (or a
+ * function of one or more fields) of the CountedCompleter object that
+ * holds the result upon completion. Method {@link #setRawResult} by
+ * default plays no role in CountedCompleters. It is possible, but
+ * rarely applicable, to override this method to maintain other
+ * objects or fields holding result data.
+ *
+ * <p>A CountedCompleter that does not itself have a completer (i.e.,
+ * one for which {@link #getCompleter} returns {@code null}) can be
+ * used as a regular ForkJoinTask with this added functionality.
+ * However, any completer that in turn has another completer serves
+ * only as an internal helper for other computations, so its own task
+ * status (as reported in methods such as {@link ForkJoinTask#isDone})
+ * is arbitrary; this status changes only upon explicit invocations of
+ * {@link #complete}, {@link ForkJoinTask#cancel}, {@link
+ * ForkJoinTask#completeExceptionally} or upon exceptional completion
+ * of method {@code compute}. Upon any exceptional completion, the
+ * exception may be relayed to a task's completer (and its completer,
+ * and so on), if one exists and it has not otherwise already
+ * completed. Similarly, cancelling an internal CountedCompleter has
+ * only a local effect on that completer, so is not often useful.
+ *
+ * <p><b>Sample Usages.</b>
+ *
+ * <p><b>Parallel recursive decomposition.</b> CountedCompleters may
+ * be arranged in trees similar to those often used with {@link
+ * RecursiveAction}s, although the constructions involved in setting
+ * them up typically vary. Here, the completer of each task is its
+ * parent in the computation tree. Even though they entail a bit more
+ * bookkeeping, CountedCompleters may be better choices when applying
+ * a possibly time-consuming operation (that cannot be further
+ * subdivided) to each element of an array or collection; especially
+ * when the operation takes a significantly different amount of time
+ * to complete for some elements than others, either because of
+ * intrinsic variation (for example I/O) or auxiliary effects such as
+ * garbage collection. Because CountedCompleters provide their own
+ * continuations, other threads need not block waiting to perform
+ * them.
+ *
+ * <p>For example, here is an initial version of a class that uses
+ * divide-by-two recursive decomposition to divide work into single
+ * pieces (leaf tasks). Even when work is split into individual calls,
+ * tree-based techniques are usually preferable to directly forking
+ * leaf tasks, because they reduce inter-thread communication and
+ * improve load balancing. In the recursive case, the second of each
+ * pair of subtasks to finish triggers completion of its parent
+ * (because no result combination is performed, the default no-op
+ * implementation of method {@code onCompletion} is not overridden). A
+ * static utility method sets up the base task and invokes it
+ * (here, implicitly using the {@link ForkJoinPool#commonPool()}).
+ *
+ * <pre> {@code
+ * class MyOperation<E> { void apply(E e) { ... } }
+ *
+ * class ForEach<E> extends CountedCompleter<Void> {
+ *
+ * public static <E> void forEach(E[] array, MyOperation<E> op) {
+ * new ForEach<E>(null, array, op, 0, array.length).invoke();
+ * }
+ *
+ * final E[] array; final MyOperation<E> op; final int lo, hi;
+ * ForEach(CountedCompleter<?> p, E[] array, MyOperation<E> op, int lo, int hi) {
+ * super(p);
+ * this.array = array; this.op = op; this.lo = lo; this.hi = hi;
+ * }
+ *
+ * public void compute() { // version 1
+ * if (hi - lo >= 2) {
+ * int mid = (lo + hi) >>> 1;
+ * setPendingCount(2); // must set pending count before fork
+ * new ForEach(this, array, op, mid, hi).fork(); // right child
+ * new ForEach(this, array, op, lo, mid).fork(); // left child
+ * }
+ * else if (hi > lo)
+ * op.apply(array[lo]);
+ * tryComplete();
+ * }
+ * }}</pre>
+ *
+ * This design can be improved by noticing that in the recursive case,
+ * the task has nothing to do after forking its right task, so can
+ * directly invoke its left task before returning. (This is an analog
+ * of tail recursion removal.) Also, because the task returns upon
+ * executing its left task (rather than falling through to invoke
+ * {@code tryComplete}) the pending count is set to one:
+ *
+ * <pre> {@code
+ * class ForEach<E> ...
+ * public void compute() { // version 2
+ * if (hi - lo >= 2) {
+ * int mid = (lo + hi) >>> 1;
+ * setPendingCount(1); // only one pending
+ * new ForEach(this, array, op, mid, hi).fork(); // right child
+ * new ForEach(this, array, op, lo, mid).compute(); // direct invoke
+ * }
+ * else {
+ * if (hi > lo)
+ * op.apply(array[lo]);
+ * tryComplete();
+ * }
+ * }
+ * }</pre>
+ *
+ * As a further improvement, notice that the left task need not even
+ * exist. Instead of creating a new one, we can iterate using the
+ * original task, and add a pending count for each fork. Additionally,
+ * because no task in this tree implements an {@link #onCompletion}
+ * method, {@code tryComplete()} can be replaced with {@link
+ * #propagateCompletion}.
+ *
+ * <pre> {@code
+ * class ForEach<E> ...
+ * public void compute() { // version 3
+ * int l = lo, h = hi;
+ * while (h - l >= 2) {
+ * int mid = (l + h) >>> 1;
+ * addToPendingCount(1);
+ * new ForEach(this, array, op, mid, h).fork(); // right child
+ * h = mid;
+ * }
+ * if (h > l)
+ * op.apply(array[l]);
+ * propagateCompletion();
+ * }
+ * }</pre>
+ *
+ * Additional improvements of such classes might entail precomputing
+ * pending counts so that they can be established in constructors,
+ * specializing classes for leaf steps, subdividing by say, four,
+ * instead of two per iteration, and using an adaptive threshold
+ * instead of always subdividing down to single elements.
+ *
+ * <p><b>Searching.</b> A tree of CountedCompleters can search for a
+ * value or property in different parts of a data structure, and
+ * report a result in an {@link
+ * java.util.concurrent.atomic.AtomicReference AtomicReference} as
+ * soon as one is found. The others can poll the result to avoid
+ * unnecessary work. (You could additionally {@linkplain #cancel
+ * cancel} other tasks, but it is usually simpler and more efficient
+ * to just let them notice that the result is set and if so skip
+ * further processing.) Illustrating again with an array using full
+ * partitioning (again, in practice, leaf tasks will almost always
+ * process more than one element):
+ *
+ * <pre> {@code
+ * class Searcher<E> extends CountedCompleter<E> {
+ * final E[] array; final AtomicReference<E> result; final int lo, hi;
+ * Searcher(CountedCompleter<?> p, E[] array, AtomicReference<E> result, int lo, int hi) {
+ * super(p);
+ * this.array = array; this.result = result; this.lo = lo; this.hi = hi;
+ * }
+ * public E getRawResult() { return result.get(); }
+ * public void compute() { // similar to ForEach version 3
+ * int l = lo, h = hi;
+ * while (result.get() == null && h >= l) {
+ * if (h - l >= 2) {
+ * int mid = (l + h) >>> 1;
+ * addToPendingCount(1);
+ * new Searcher(this, array, result, mid, h).fork();
+ * h = mid;
+ * }
+ * else {
+ * E x = array[l];
+ * if (matches(x) && result.compareAndSet(null, x))
+ * quietlyCompleteRoot(); // root task is now joinable
+ * break;
+ * }
+ * }
+ * tryComplete(); // normally complete whether or not found
+ * }
+ * boolean matches(E e) { ... } // return true if found
+ *
+ * public static <E> E search(E[] array) {
+ * return new Searcher<E>(null, array, new AtomicReference<E>(), 0, array.length).invoke();
+ * }
+ * }}</pre>
+ *
+ * In this example, as well as others in which tasks have no other
+ * effects except to compareAndSet a common result, the trailing
+ * unconditional invocation of {@code tryComplete} could be made
+ * conditional ({@code if (result.get() == null) tryComplete();})
+ * because no further bookkeeping is required to manage completions
+ * once the root task completes.
+ *
+ * <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
+ * results of multiple subtasks usually need to access these results
+ * in method {@link #onCompletion}. As illustrated in the following
+ * class (that performs a simplified form of map-reduce where mappings
+ * and reductions are all of type {@code E}), one way to do this in
+ * divide and conquer designs is to have each subtask record its
+ * sibling, so that it can be accessed in method {@code onCompletion}.
+ * This technique applies to reductions in which the order of
+ * combining left and right results does not matter; ordered
+ * reductions require explicit left/right designations. Variants of
+ * other streamlinings seen in the above examples may also apply.
+ *
+ * <pre> {@code
+ * class MyMapper<E> { E apply(E v) { ... } }
+ * class MyReducer<E> { E apply(E x, E y) { ... } }
+ * class MapReducer<E> extends CountedCompleter<E> {
+ * final E[] array; final MyMapper<E> mapper;
+ * final MyReducer<E> reducer; final int lo, hi;
+ * MapReducer<E> sibling;
+ * E result;
+ * MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
+ * MyReducer<E> reducer, int lo, int hi) {
+ * super(p);
+ * this.array = array; this.mapper = mapper;
+ * this.reducer = reducer; this.lo = lo; this.hi = hi;
+ * }
+ * public void compute() {
+ * if (hi - lo >= 2) {
+ * int mid = (lo + hi) >>> 1;
+ * MapReducer<E> left = new MapReducer(this, array, mapper, reducer, lo, mid);
+ * MapReducer<E> right = new MapReducer(this, array, mapper, reducer, mid, hi);
+ * left.sibling = right;
+ * right.sibling = left;
+ * setPendingCount(1); // only right is pending
+ * right.fork();
+ * left.compute(); // directly execute left
+ * }
+ * else {
+ * if (hi > lo)
+ * result = mapper.apply(array[lo]);
+ * tryComplete();
+ * }
+ * }
+ * public void onCompletion(CountedCompleter<?> caller) {
+ * if (caller != this) {
+ * MapReducer<E> child = (MapReducer<E>)caller;
+ * MapReducer<E> sib = child.sibling;
+ * if (sib == null || sib.result == null)
+ * result = child.result;
+ * else
+ * result = reducer.apply(child.result, sib.result);
+ * }
+ * }
+ * public E getRawResult() { return result; }
+ *
+ * public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
+ * return new MapReducer<E>(null, array, mapper, reducer,
+ * 0, array.length).invoke();
+ * }
+ * }}</pre>
+ *
+ * Here, method {@code onCompletion} takes a form common to many
+ * completion designs that combine results. This callback-style method
+ * is triggered once per task, in either of the two different contexts
+ * in which the pending count is, or becomes, zero: (1) by a task
+ * itself, if its pending count is zero upon invocation of {@code
+ * tryComplete}, or (2) by any of its subtasks when they complete and
+ * decrement the pending count to zero. The {@code caller} argument
+ * distinguishes cases. Most often, when the caller is {@code this},
+ * no action is necessary. Otherwise the caller argument can be used
+ * (usually via a cast) to supply a value (and/or links to other
+ * values) to be combined. Assuming proper use of pending counts, the
+ * actions inside {@code onCompletion} occur (once) upon completion of
+ * a task and its subtasks. No additional synchronization is required
+ * within this method to ensure thread safety of accesses to fields of
+ * this task or other completed tasks.
+ *
+ * <p><b>Completion Traversals</b>. If using {@code onCompletion} to
+ * process completions is inapplicable or inconvenient, you can use
+ * methods {@link #firstComplete} and {@link #nextComplete} to create
+ * custom traversals. For example, to define a MapReducer that only
+ * splits out right-hand tasks in the form of the third ForEach
+ * example, the completions must cooperatively reduce along
+ * unexhausted subtask links, which can be done as follows:
+ *
+ * <pre> {@code
+ * class MapReducer<E> extends CountedCompleter<E> { // version 2
+ * final E[] array; final MyMapper<E> mapper;
+ * final MyReducer<E> reducer; final int lo, hi;
+ * MapReducer<E> forks, next; // record subtask forks in list
+ * E result;
+ * MapReducer(CountedCompleter<?> p, E[] array, MyMapper<E> mapper,
+ * MyReducer<E> reducer, int lo, int hi, MapReducer<E> next) {
+ * super(p);
+ * this.array = array; this.mapper = mapper;
+ * this.reducer = reducer; this.lo = lo; this.hi = hi;
+ * this.next = next;
+ * }
+ * public void compute() {
+ * int l = lo, h = hi;
+ * while (h - l >= 2) {
+ * int mid = (l + h) >>> 1;
+ * addToPendingCount(1);
+ * (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
+ * h = mid;
+ * }
+ * if (h > l)
+ * result = mapper.apply(array[l]);
+ * // process completions by reducing along and advancing subtask links
+ * for (CountedCompleter<?> c = firstComplete(); c != null; c = c.nextComplete()) {
+ * for (MapReducer t = (MapReducer)c, s = t.forks; s != null; s = t.forks = s.next)
+ * t.result = reducer.apply(t.result, s.result);
+ * }
+ * }
+ * public E getRawResult() { return result; }
+ *
+ * public static <E> E mapReduce(E[] array, MyMapper<E> mapper, MyReducer<E> reducer) {
+ * return new MapReducer<E>(null, array, mapper, reducer,
+ * 0, array.length, null).invoke();
+ * }
+ * }}</pre>
+ *
+ * <p><b>Triggers.</b> Some CountedCompleters are themselves never
+ * forked, but instead serve as bits of plumbing in other designs;
+ * including those in which the completion of one of more async tasks
+ * triggers another async task. For example:
+ *
+ * <pre> {@code
+ * class HeaderBuilder extends CountedCompleter<...> { ... }
+ * class BodyBuilder extends CountedCompleter<...> { ... }
+ * class PacketSender extends CountedCompleter<...> {
+ * PacketSender(...) { super(null, 1); ... } // trigger on second completion
+ * public void compute() { } // never called
+ * public void onCompletion(CountedCompleter<?> caller) { sendPacket(); }
+ * }
+ * // sample use:
+ * PacketSender p = new PacketSender();
+ * new HeaderBuilder(p, ...).fork();
+ * new BodyBuilder(p, ...).fork();
+ * }</pre>
+ *
+ * @since 1.8
+ * @hide
+ * @author Doug Lea
+ */
+public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
+ private static final long serialVersionUID = 5232453752276485070L;
+
+ /** This task's completer, or null if none */
+ final CountedCompleter<?> completer;
+ /** The number of pending tasks until completion */
+ volatile int pending;
+
+ /**
+ * Creates a new CountedCompleter with the given completer
+ * and initial pending count.
+ *
+ * @param completer this task's completer, or {@code null} if none
+ * @param initialPendingCount the initial pending count
+ */
+ protected CountedCompleter(CountedCompleter<?> completer,
+ int initialPendingCount) {
+ this.completer = completer;
+ this.pending = initialPendingCount;
+ }
+
+ /**
+ * Creates a new CountedCompleter with the given completer
+ * and an initial pending count of zero.
+ *
+ * @param completer this task's completer, or {@code null} if none
+ */
+ protected CountedCompleter(CountedCompleter<?> completer) {
+ this.completer = completer;
+ }
+
+ /**
+ * Creates a new CountedCompleter with no completer
+ * and an initial pending count of zero.
+ */
+ protected CountedCompleter() {
+ this.completer = null;
+ }
+
+ /**
+ * The main computation performed by this task.
+ */
+ public abstract void compute();
+
+ /**
+ * Performs an action when method {@link #tryComplete} is invoked
+ * and the pending count is zero, or when the unconditional
+ * method {@link #complete} is invoked. By default, this method
+ * does nothing. You can distinguish cases by checking the
+ * identity of the given caller argument. If not equal to {@code
+ * this}, then it is typically a subtask that may contain results
+ * (and/or links to other results) to combine.
+ *
+ * @param caller the task invoking this method (which may
+ * be this task itself)
+ */
+ public void onCompletion(CountedCompleter<?> caller) {
+ }
+
+ /**
+ * Performs an action when method {@link #completeExceptionally}
+ * is invoked or method {@link #compute} throws an exception, and
+ * this task has not otherwise already completed normally. On
+ * entry to this method, this task {@link
+ * ForkJoinTask#isCompletedAbnormally}. The return value of this
+ * method controls further propagation: If {@code true} and this
+ * task has a completer, then this completer is also completed
+ * exceptionally. The default implementation of this method does
+ * nothing except return {@code true}.
+ *
+ * @param ex the exception
+ * @param caller the task invoking this method (which may
+ * be this task itself)
+ * @return true if this exception should be propagated to this
+ * task's completer, if one exists
+ */
+ public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
+ return true;
+ }
+
+ /**
+ * Returns the completer established in this task's constructor,
+ * or {@code null} if none.
+ *
+ * @return the completer
+ */
+ public final CountedCompleter<?> getCompleter() {
+ return completer;
+ }
+
+ /**
+ * Returns the current pending count.
+ *
+ * @return the current pending count
+ */
+ public final int getPendingCount() {
+ return pending;
+ }
+
+ /**
+ * Sets the pending count to the given value.
+ *
+ * @param count the count
+ */
+ public final void setPendingCount(int count) {
+ pending = count;
+ }
+
+ /**
+ * Adds (atomically) the given value to the pending count.
+ *
+ * @param delta the value to add
+ */
+ public final void addToPendingCount(int delta) {
+ int c; // note: can replace with intrinsic in jdk8
+ do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta));
+ }
+
+ /**
+ * Sets (atomically) the pending count to the given count only if
+ * it currently holds the given expected value.
+ *
+ * @param expected the expected value
+ * @param count the new value
+ * @return true if successful
+ */
+ public final boolean compareAndSetPendingCount(int expected, int count) {
+ return U.compareAndSwapInt(this, PENDING, expected, count);
+ }
+
+ /**
+ * If the pending count is nonzero, (atomically) decrements it.
+ *
+ * @return the initial (undecremented) pending count holding on entry
+ * to this method
+ */
+ public final int decrementPendingCountUnlessZero() {
+ int c;
+ do {} while ((c = pending) != 0 &&
+ !U.compareAndSwapInt(this, PENDING, c, c - 1));
+ return c;
+ }
+
+ /**
+ * Returns the root of the current computation; i.e., this
+ * task if it has no completer, else its completer's root.
+ *
+ * @return the root of the current computation
+ */
+ public final CountedCompleter<?> getRoot() {
+ CountedCompleter<?> a = this, p;
+ while ((p = a.completer) != null)
+ a = p;
+ return a;
+ }
+
+ /**
+ * If the pending count is nonzero, decrements the count;
+ * otherwise invokes {@link #onCompletion} and then similarly
+ * tries to complete this task's completer, if one exists,
+ * else marks this task as complete.
+ */
+ public final void tryComplete() {
+ CountedCompleter<?> a = this, s = a;
+ for (int c;;) {
+ if ((c = a.pending) == 0) {
+ a.onCompletion(s);
+ if ((a = (s = a).completer) == null) {
+ s.quietlyComplete();
+ return;
+ }
+ }
+ else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+ return;
+ }
+ }
+
+ /**
+ * Equivalent to {@link #tryComplete} but does not invoke {@link
+ * #onCompletion} along the completion path: If the pending count
+ * is nonzero, decrements the count; otherwise, similarly tries to
+ * complete this task's completer, if one exists, else marks this
+ * task as complete. This method may be useful in cases where
+ * {@code onCompletion} should not, or need not, be invoked for
+ * each completer in a computation.
+ */
+ public final void propagateCompletion() {
+ CountedCompleter<?> a = this, s = a;
+ for (int c;;) {
+ if ((c = a.pending) == 0) {
+ if ((a = (s = a).completer) == null) {
+ s.quietlyComplete();
+ return;
+ }
+ }
+ else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+ return;
+ }
+ }
+
+ /**
+ * Regardless of pending count, invokes {@link #onCompletion},
+ * marks this task as complete and further triggers {@link
+ * #tryComplete} on this task's completer, if one exists. The
+ * given rawResult is used as an argument to {@link #setRawResult}
+ * before invoking {@link #onCompletion} or marking this task as
+ * complete; its value is meaningful only for classes overriding
+ * {@code setRawResult}.
+ *
+ * <p>This method may be useful when forcing completion as soon as
+ * any one (versus all) of several subtask results are obtained.
+ * However, in the common (and recommended) case in which {@code
+ * setRawResult} is not overridden, this effect can be obtained
+ * more simply using {@code quietlyCompleteRoot();}.
+ *
+ * @param rawResult the raw result
+ */
+ public void complete(T rawResult) {
+ CountedCompleter<?> p;
+ setRawResult(rawResult);
+ onCompletion(this);
+ quietlyComplete();
+ if ((p = completer) != null)
+ p.tryComplete();
+ }
+
+
+ /**
+ * If this task's pending count is zero, returns this task;
+ * otherwise decrements its pending count and returns {@code
+ * null}. This method is designed to be used with {@link
+ * #nextComplete} in completion traversal loops.
+ *
+ * @return this task, if pending count was zero, else {@code null}
+ */
+ public final CountedCompleter<?> firstComplete() {
+ for (int c;;) {
+ if ((c = pending) == 0)
+ return this;
+ else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
+ return null;
+ }
+ }
+
+ /**
+ * If this task does not have a completer, invokes {@link
+ * ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
+ * the completer's pending count is non-zero, decrements that
+ * pending count and returns {@code null}. Otherwise, returns the
+ * completer. This method can be used as part of a completion
+ * traversal loop for homogeneous task hierarchies:
+ *
+ * <pre> {@code
+ * for (CountedCompleter<?> c = firstComplete();
+ * c != null;
+ * c = c.nextComplete()) {
+ * // ... process c ...
+ * }}</pre>
+ *
+ * @return the completer, or {@code null} if none
+ */
+ public final CountedCompleter<?> nextComplete() {
+ CountedCompleter<?> p;
+ if ((p = completer) != null)
+ return p.firstComplete();
+ else {
+ quietlyComplete();
+ return null;
+ }
+ }
+
+ /**
+ * Equivalent to {@code getRoot().quietlyComplete()}.
+ */
+ public final void quietlyCompleteRoot() {
+ for (CountedCompleter<?> a = this, p;;) {
+ if ((p = a.completer) == null) {
+ a.quietlyComplete();
+ return;
+ }
+ a = p;
+ }
+ }
+
+ /**
+ * Supports ForkJoinTask exception propagation.
+ */
+ void internalPropagateException(Throwable ex) {
+ CountedCompleter<?> a = this, s = a;
+ while (a.onExceptionalCompletion(ex, s) &&
+ (a = (s = a).completer) != null && a.status >= 0)
+ a.recordExceptionalCompletion(ex);
+ }
+
+ /**
+ * Implements execution conventions for CountedCompleters.
+ */
+ protected final boolean exec() {
+ compute();
+ return false;
+ }
+
+ /**
+ * Returns the result of the computation. By default
+ * returns {@code null}, which is appropriate for {@code Void}
+ * actions, but in other cases should be overridden, almost
+ * always to return a field or function of a field that
+ * holds the result upon completion.
+ *
+ * @return the result of the computation
+ */
+ public T getRawResult() { return null; }
+
+ /**
+ * A method that result-bearing CountedCompleters may optionally
+ * use to help maintain result data. By default, does nothing.
+ * Overrides are not recommended. However, if this method is
+ * overridden to update existing objects or fields, then it must
+ * in general be defined to be thread-safe.
+ */
+ protected void setRawResult(T t) { }
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe U;
+ private static final long PENDING;
+ static {
+ try {
+ U = sun.misc.Unsafe.getUnsafe();
+ PENDING = U.objectFieldOffset
+ (CountedCompleter.class.getDeclaredField("pending"));
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+}
diff --git a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
index cf0b46e..e1a7bee 100644
--- a/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
+++ b/luni/src/main/java/java/util/concurrent/CyclicBarrier.java
@@ -5,7 +5,8 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
/**
* A synchronization aid that allows a set of threads to all wait for
@@ -15,7 +16,7 @@
* <em>cyclic</em> because it can be re-used after the waiting threads
* are released.
*
- * <p>A <tt>CyclicBarrier</tt> supports an optional {@link Runnable} command
+ * <p>A {@code CyclicBarrier} supports an optional {@link Runnable} command
* that is run once per barrier point, after the last thread in the party
* arrives, but before any threads are released.
* This <em>barrier action</em> is useful
@@ -68,8 +69,8 @@
* barrier until all rows have been processed. When all rows are processed
* the supplied {@link Runnable} barrier action is executed and merges the
* rows. If the merger
- * determines that a solution has been found then <tt>done()</tt> will return
- * <tt>true</tt> and each worker will terminate.
+ * determines that a solution has been found then {@code done()} will return
+ * {@code true} and each worker will terminate.
*
* <p>If the barrier action does not rely on the parties being suspended when
* it is executed, then any of the threads in the party could execute that
@@ -82,7 +83,7 @@
* // log the completion of this iteration
* }}</pre>
*
- * <p>The <tt>CyclicBarrier</tt> uses an all-or-none breakage model
+ * <p>The {@code CyclicBarrier} uses an all-or-none breakage model
* for failed synchronization attempts: If a thread leaves a barrier
* point prematurely because of interruption, failure, or timeout, all
* other threads waiting at that barrier point will also leave
@@ -109,7 +110,7 @@
* is reset. There can be many generations associated with threads
* using the barrier - due to the non-deterministic way the lock
* may be allocated to waiting threads - but only one of these
- * can be active at a time (the one to which <tt>count</tt> applies)
+ * can be active at a time (the one to which {@code count} applies)
* and all the rest are either broken or tripped.
* There need not be an active generation if there has been a break
* but no subsequent reset.
@@ -229,7 +230,7 @@
}
/**
- * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and which
* will execute the given barrier action when the barrier is tripped,
* performed by the last thread entering the barrier.
@@ -248,7 +249,7 @@
}
/**
- * Creates a new <tt>CyclicBarrier</tt> that will trip when the
+ * Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and
* does not perform a predefined action when the barrier is tripped.
*
@@ -271,7 +272,7 @@
/**
* Waits until all {@linkplain #getParties parties} have invoked
- * <tt>await</tt> on this barrier.
+ * {@code await} on this barrier.
*
* <p>If the current thread is not the last to arrive then it is
* disabled for thread scheduling purposes and lies dormant until
@@ -296,7 +297,7 @@
*
* <p>If the barrier is {@link #reset} while any thread is waiting,
* or if the barrier {@linkplain #isBroken is broken} when
- * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@code await} is invoked, or while any thread is waiting, then
* {@link BrokenBarrierException} is thrown.
*
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while waiting,
@@ -313,7 +314,7 @@
* the broken state.
*
* @return the arrival index of the current thread, where index
- * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * {@code getParties() - 1} indicates the first
* to arrive and zero indicates the last to arrive
* @throws InterruptedException if the current thread was interrupted
* while waiting
@@ -321,7 +322,7 @@
* interrupted or timed out while the current thread was
* waiting, or the barrier was reset, or the barrier was
* broken when {@code await} was called, or the barrier
- * action (if present) failed due an exception.
+ * action (if present) failed due to an exception
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
@@ -333,7 +334,7 @@
/**
* Waits until all {@linkplain #getParties parties} have invoked
- * <tt>await</tt> on this barrier, or the specified waiting time elapses.
+ * {@code await} on this barrier, or the specified waiting time elapses.
*
* <p>If the current thread is not the last to arrive then it is
* disabled for thread scheduling purposes and lies dormant until
@@ -363,7 +364,7 @@
*
* <p>If the barrier is {@link #reset} while any thread is waiting,
* or if the barrier {@linkplain #isBroken is broken} when
- * <tt>await</tt> is invoked, or while any thread is waiting, then
+ * {@code await} is invoked, or while any thread is waiting, then
* {@link BrokenBarrierException} is thrown.
*
* <p>If any thread is {@linkplain Thread#interrupt interrupted} while
@@ -382,7 +383,7 @@
* @param timeout the time to wait for the barrier
* @param unit the time unit of the timeout parameter
* @return the arrival index of the current thread, where index
- * <tt>{@link #getParties()} - 1</tt> indicates the first
+ * {@code getParties() - 1} indicates the first
* to arrive and zero indicates the last to arrive
* @throws InterruptedException if the current thread was interrupted
* while waiting
@@ -391,7 +392,7 @@
* interrupted or timed out while the current thread was
* waiting, or the barrier was reset, or the barrier was broken
* when {@code await} was called, or the barrier action (if
- * present) failed due an exception
+ * present) failed due to an exception
*/
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
diff --git a/luni/src/main/java/java/util/concurrent/DelayQueue.java b/luni/src/main/java/java/util/concurrent/DelayQueue.java
index 52028cb..945249e 100644
--- a/luni/src/main/java/java/util/concurrent/DelayQueue.java
+++ b/luni/src/main/java/java/util/concurrent/DelayQueue.java
@@ -4,7 +4,6 @@
* http://creativecommons.org/publicdomain/zero/1.0/
*/
-
package java.util.concurrent;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
import java.util.concurrent.locks.Condition;
@@ -17,15 +16,15 @@
/**
* An unbounded {@linkplain BlockingQueue blocking queue} of
- * <tt>Delayed</tt> elements, in which an element can only be taken
+ * {@code Delayed} elements, in which an element can only be taken
* when its delay has expired. The <em>head</em> of the queue is that
- * <tt>Delayed</tt> element whose delay expired furthest in the
- * past. If no delay has expired there is no head and <tt>poll</tt>
- * will return <tt>null</tt>. Expiration occurs when an element's
- * <tt>getDelay(TimeUnit.NANOSECONDS)</tt> method returns a value less
+ * {@code Delayed} element whose delay expired furthest in the
+ * past. If no delay has expired there is no head and {@code poll}
+ * will return {@code null}. Expiration occurs when an element's
+ * {@code getDelay(TimeUnit.NANOSECONDS)} method returns a value less
* than or equal to zero. Even though unexpired elements cannot be
- * removed using <tt>take</tt> or <tt>poll</tt>, they are otherwise
- * treated as normal elements. For example, the <tt>size</tt> method
+ * removed using {@code take} or {@code poll}, they are otherwise
+ * treated as normal elements. For example, the {@code size} method
* returns the count of both expired and unexpired elements.
* This queue does not permit null elements.
*
@@ -39,11 +38,10 @@
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
-
public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
implements BlockingQueue<E> {
- private transient final ReentrantLock lock = new ReentrantLock();
+ private final transient ReentrantLock lock = new ReentrantLock();
private final PriorityQueue<E> q = new PriorityQueue<E>();
/**
@@ -72,12 +70,12 @@
private final Condition available = lock.newCondition();
/**
- * Creates a new <tt>DelayQueue</tt> that is initially empty.
+ * Creates a new {@code DelayQueue} that is initially empty.
*/
public DelayQueue() {}
/**
- * Creates a <tt>DelayQueue</tt> initially containing the elements of the
+ * Creates a {@code DelayQueue} initially containing the elements of the
* given collection of {@link Delayed} instances.
*
* @param c the collection of elements to initially contain
@@ -92,7 +90,7 @@
* Inserts the specified element into this delay queue.
*
* @param e the element to add
- * @return <tt>true</tt> (as specified by {@link Collection#add})
+ * @return {@code true} (as specified by {@link Collection#add})
* @throws NullPointerException if the specified element is null
*/
public boolean add(E e) {
@@ -103,7 +101,7 @@
* Inserts the specified element into this delay queue.
*
* @param e the element to add
- * @return <tt>true</tt>
+ * @return {@code true}
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
@@ -139,7 +137,7 @@
* @param e the element to add
* @param timeout This parameter is ignored as the method never blocks
* @param unit This parameter is ignored as the method never blocks
- * @return <tt>true</tt>
+ * @return {@code true}
* @throws NullPointerException {@inheritDoc}
*/
public boolean offer(E e, long timeout, TimeUnit unit) {
@@ -147,10 +145,10 @@
}
/**
- * Retrieves and removes the head of this queue, or returns <tt>null</tt>
+ * Retrieves and removes the head of this queue, or returns {@code null}
* if this queue has no elements with an expired delay.
*
- * @return the head of this queue, or <tt>null</tt> if this
+ * @return the head of this queue, or {@code null} if this
* queue has no elements with an expired delay
*/
public E poll() {
@@ -186,7 +184,8 @@
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return q.poll();
- else if (leader != null)
+ first = null; // don't retain ref while waiting
+ if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
@@ -212,7 +211,7 @@
* until an element with an expired delay is available on this queue,
* or the specified wait time expires.
*
- * @return the head of this queue, or <tt>null</tt> if the
+ * @return the head of this queue, or {@code null} if the
* specified waiting time elapses before an element with
* an expired delay becomes available
* @throws InterruptedException {@inheritDoc}
@@ -235,6 +234,7 @@
return q.poll();
if (nanos <= 0)
return null;
+ first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
@@ -259,13 +259,13 @@
/**
* Retrieves, but does not remove, the head of this queue, or
- * returns <tt>null</tt> if this queue is empty. Unlike
- * <tt>poll</tt>, if no expired elements are available in the queue,
+ * returns {@code null} if this queue is empty. Unlike
+ * {@code poll}, if no expired elements are available in the queue,
* this method returns the element that will expire next,
* if one exists.
*
- * @return the head of this queue, or <tt>null</tt> if this
- * queue is empty.
+ * @return the head of this queue, or {@code null} if this
+ * queue is empty
*/
public E peek() {
final ReentrantLock lock = this.lock;
@@ -288,7 +288,7 @@
}
/**
- * Return first element only if it is expired.
+ * Returns first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private E peekExpired() {
@@ -369,10 +369,10 @@
}
/**
- * Always returns <tt>Integer.MAX_VALUE</tt> because
- * a <tt>DelayQueue</tt> is not capacity constrained.
+ * Always returns {@code Integer.MAX_VALUE} because
+ * a {@code DelayQueue} is not capacity constrained.
*
- * @return <tt>Integer.MAX_VALUE</tt>
+ * @return {@code Integer.MAX_VALUE}
*/
public int remainingCapacity() {
return Integer.MAX_VALUE;
@@ -412,7 +412,7 @@
* <p>If this queue fits in the specified array with room to spare
* (i.e., the array has more elements than this queue), the element in
* the array immediately following the end of the queue is set to
- * <tt>null</tt>.
+ * {@code null}.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
@@ -420,12 +420,12 @@
* under certain circumstances, be used to save allocation costs.
*
* <p>The following code can be used to dump a delay queue into a newly
- * allocated array of <tt>Delayed</tt>:
+ * allocated array of {@code Delayed}:
*
* <pre> {@code Delayed[] a = q.toArray(new Delayed[0]);}</pre>
*
- * Note that <tt>toArray(new Object[0])</tt> is identical in function to
- * <tt>toArray()</tt>.
+ * Note that {@code toArray(new Object[0])} is identical in function to
+ * {@code toArray()}.
*
* @param a the array into which the elements of the queue are to
* be stored, if it is big enough; otherwise, a new array of the
diff --git a/luni/src/main/java/java/util/concurrent/Delayed.java b/luni/src/main/java/java/util/concurrent/Delayed.java
index 39d927c..6a9527d 100644
--- a/luni/src/main/java/java/util/concurrent/Delayed.java
+++ b/luni/src/main/java/java/util/concurrent/Delayed.java
@@ -11,8 +11,8 @@
* acted upon after a given delay.
*
* <p>An implementation of this interface must define a
- * <tt>compareTo</tt> method that provides an ordering consistent with
- * its <tt>getDelay</tt> method.
+ * {@code compareTo} method that provides an ordering consistent with
+ * its {@code getDelay} method.
*
* @since 1.5
* @author Doug Lea
diff --git a/luni/src/main/java/java/util/concurrent/Exchanger.java b/luni/src/main/java/java/util/concurrent/Exchanger.java
index 6069dce..01d5960 100644
--- a/luni/src/main/java/java/util/concurrent/Exchanger.java
+++ b/luni/src/main/java/java/util/concurrent/Exchanger.java
@@ -6,7 +6,8 @@
*/
package java.util.concurrent;
-import java.util.concurrent.atomic.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;
/**
@@ -73,486 +74,427 @@
* @param <V> The type of objects that may be exchanged
*/
public class Exchanger<V> {
+
/*
- * Algorithm Description:
+ * Overview: The core algorithm is, for an exchange "slot",
+ * and a participant (caller) with an item:
*
- * The basic idea is to maintain a "slot", which is a reference to
- * a Node containing both an Item to offer and a "hole" waiting to
- * get filled in. If an incoming "occupying" thread sees that the
- * slot is null, it CAS'es (compareAndSets) a Node there and waits
- * for another to invoke exchange. That second "fulfilling" thread
- * sees that the slot is non-null, and so CASes it back to null,
- * also exchanging items by CASing the hole, plus waking up the
- * occupying thread if it is blocked. In each case CAS'es may
- * fail because a slot at first appears non-null but is null upon
- * CAS, or vice-versa. So threads may need to retry these
- * actions.
+ * for (;;) {
+ * if (slot is empty) { // offer
+ * place item in a Node;
+ * if (can CAS slot from empty to node) {
+ * wait for release;
+ * return matching item in node;
+ * }
+ * }
+ * else if (can CAS slot from node to empty) { // release
+ * get the item in node;
+ * set matching item in node;
+ * release waiting thread;
+ * }
+ * // else retry on CAS failure
+ * }
*
- * This simple approach works great when there are only a few
- * threads using an Exchanger, but performance rapidly
- * deteriorates due to CAS contention on the single slot when
- * there are lots of threads using an exchanger. So instead we use
- * an "arena"; basically a kind of hash table with a dynamically
- * varying number of slots, any one of which can be used by
- * threads performing an exchange. Incoming threads pick slots
- * based on a hash of their Thread ids. If an incoming thread
- * fails to CAS in its chosen slot, it picks an alternative slot
- * instead. And similarly from there. If a thread successfully
- * CASes into a slot but no other thread arrives, it tries
- * another, heading toward the zero slot, which always exists even
- * if the table shrinks. The particular mechanics controlling this
- * are as follows:
+ * This is among the simplest forms of a "dual data structure" --
+ * see Scott and Scherer's DISC 04 paper and
+ * http://www.cs.rochester.edu/research/synchronization/pseudocode/duals.html
*
- * Waiting: Slot zero is special in that it is the only slot that
- * exists when there is no contention. A thread occupying slot
- * zero will block if no thread fulfills it after a short spin.
- * In other cases, occupying threads eventually give up and try
- * another slot. Waiting threads spin for a while (a period that
- * should be a little less than a typical context-switch time)
- * before either blocking (if slot zero) or giving up (if other
- * slots) and restarting. There is no reason for threads to block
- * unless there are unlikely to be any other threads present.
- * Occupants are mainly avoiding memory contention so sit there
- * quietly polling for a shorter period than it would take to
- * block and then unblock them. Non-slot-zero waits that elapse
- * because of lack of other threads waste around one extra
- * context-switch time per try, which is still on average much
- * faster than alternative approaches.
+ * This works great in principle. But in practice, like many
+ * algorithms centered on atomic updates to a single location, it
+ * scales horribly when there are more than a few participants
+ * using the same Exchanger. So the implementation instead uses a
+ * form of elimination arena, that spreads out this contention by
+ * arranging that some threads typically use different slots,
+ * while still ensuring that eventually, any two parties will be
+ * able to exchange items. That is, we cannot completely partition
+ * across threads, but instead give threads arena indices that
+ * will on average grow under contention and shrink under lack of
+ * contention. We approach this by defining the Nodes that we need
+ * anyway as ThreadLocals, and include in them per-thread index
+ * and related bookkeeping state. (We can safely reuse per-thread
+ * nodes rather than creating them fresh each time because slots
+ * alternate between pointing to a node vs null, so cannot
+ * encounter ABA problems. However, we do need some care in
+ * resetting them between uses.)
*
- * Sizing: Usually, using only a few slots suffices to reduce
- * contention. Especially with small numbers of threads, using
- * too many slots can lead to just as poor performance as using
- * too few of them, and there's not much room for error. The
- * variable "max" maintains the number of slots actually in
- * use. It is increased when a thread sees too many CAS
- * failures. (This is analogous to resizing a regular hash table
- * based on a target load factor, except here, growth steps are
- * just one-by-one rather than proportional.) Growth requires
- * contention failures in each of three tried slots. Requiring
- * multiple failures for expansion copes with the fact that some
- * failed CASes are not due to contention but instead to simple
- * races between two threads or thread pre-emptions occurring
- * between reading and CASing. Also, very transient peak
- * contention can be much higher than the average sustainable
- * levels. An attempt to decrease the max limit is usually made
- * when a non-slot-zero wait elapses without being fulfilled.
- * Threads experiencing elapsed waits move closer to zero, so
- * eventually find existing (or future) threads even if the table
- * has been shrunk due to inactivity. The chosen mechanics and
- * thresholds for growing and shrinking are intrinsically
- * entangled with indexing and hashing inside the exchange code,
- * and can't be nicely abstracted out.
+ * Implementing an effective arena requires allocating a bunch of
+ * space, so we only do so upon detecting contention (except on
+ * uniprocessors, where they wouldn't help, so aren't used).
+ * Otherwise, exchanges use the single-slot slotExchange method.
+ * On contention, not only must the slots be in different
+ * locations, but the locations must not encounter memory
+ * contention due to being on the same cache line (or more
+ * generally, the same coherence unit). Because, as of this
+ * writing, there is no way to determine cacheline size, we define
+ * a value that is enough for common platforms. Additionally,
+ * extra care elsewhere is taken to avoid other false/unintended
+ * sharing and to enhance locality, including adding padding to
+ * Nodes, embedding "bound" as an Exchanger field, and reworking
+ * some park/unpark mechanics compared to LockSupport versions.
*
- * Hashing: Each thread picks its initial slot to use in accord
- * with a simple hashcode. The sequence is the same on each
- * encounter by any given thread, but effectively random across
- * threads. Using arenas encounters the classic cost vs quality
- * tradeoffs of all hash tables. Here, we use a one-step FNV-1a
- * hash code based on the current thread's Thread.getId(), along
- * with a cheap approximation to a mod operation to select an
- * index. The downside of optimizing index selection in this way
- * is that the code is hardwired to use a maximum table size of
- * 32. But this value more than suffices for known platforms and
- * applications.
+ * The arena starts out with only one used slot. We expand the
+ * effective arena size by tracking collisions; i.e., failed CASes
+ * while trying to exchange. By nature of the above algorithm, the
+ * only kinds of collision that reliably indicate contention are
+ * when two attempted releases collide -- one of two attempted
+ * offers can legitimately fail to CAS without indicating
+ * contention by more than one other thread. (Note: it is possible
+ * but not worthwhile to more precisely detect contention by
+ * reading slot values after CAS failures.) When a thread has
+ * collided at each slot within the current arena bound, it tries
+ * to expand the arena size by one. We track collisions within
+ * bounds by using a version (sequence) number on the "bound"
+ * field, and conservatively reset collision counts when a
+ * participant notices that bound has been updated (in either
+ * direction).
*
- * Probing: On sensed contention of a selected slot, we probe
- * sequentially through the table, analogously to linear probing
- * after collision in a hash table. (We move circularly, in
- * reverse order, to mesh best with table growth and shrinkage
- * rules.) Except that to minimize the effects of false-alarms
- * and cache thrashing, we try the first selected slot twice
- * before moving.
+ * The effective arena size is reduced (when there is more than
+ * one slot) by giving up on waiting after a while and trying to
+ * decrement the arena size on expiration. The value of "a while"
+ * is an empirical matter. We implement by piggybacking on the
+ * use of spin->yield->block that is essential for reasonable
+ * waiting performance anyway -- in a busy exchanger, offers are
+ * usually almost immediately released, in which case context
+ * switching on multiprocessors is extremely slow/wasteful. Arena
+ * waits just omit the blocking part, and instead cancel. The spin
+ * count is empirically chosen to be a value that avoids blocking
+ * 99% of the time under maximum sustained exchange rates on a
+ * range of test machines. Spins and yields entail some limited
+ * randomness (using a cheap xorshift) to avoid regular patterns
+ * that can induce unproductive grow/shrink cycles. (Using a
+ * pseudorandom also helps regularize spin cycle duration by
+ * making branches unpredictable.) Also, during an offer, a
+ * waiter can "know" that it will be released when its slot has
+ * changed, but cannot yet proceed until match is set. In the
+ * mean time it cannot cancel the offer, so instead spins/yields.
+ * Note: It is possible to avoid this secondary check by changing
+ * the linearization point to be a CAS of the match field (as done
+ * in one case in the Scott & Scherer DISC paper), which also
+ * increases asynchrony a bit, at the expense of poorer collision
+ * detection and inability to always reuse per-thread nodes. So
+ * the current scheme is typically a better tradeoff.
*
- * Padding: Even with contention management, slots are heavily
- * contended, so use cache-padding to avoid poor memory
- * performance. Because of this, slots are lazily constructed
- * only when used, to avoid wasting this space unnecessarily.
- * While isolation of locations is not much of an issue at first
- * in an application, as time goes on and garbage-collectors
- * perform compaction, slots are very likely to be moved adjacent
- * to each other, which can cause much thrashing of cache lines on
- * MPs unless padding is employed.
+ * On collisions, indices traverse the arena cyclically in reverse
+ * order, restarting at the maximum index (which will tend to be
+ * sparsest) when bounds change. (On expirations, indices instead
+ * are halved until reaching 0.) It is possible (and has been
+ * tried) to use randomized, prime-value-stepped, or double-hash
+ * style traversal instead of simple cyclic traversal to reduce
+ * bunching. But empirically, whatever benefits these may have
+ * don't overcome their added overhead: We are managing operations
+ * that occur very quickly unless there is sustained contention,
+ * so simpler/faster control policies work better than more
+ * accurate but slower ones.
*
- * This is an improvement of the algorithm described in the paper
- * "A Scalable Elimination-based Exchange Channel" by William
- * Scherer, Doug Lea, and Michael Scott in Proceedings of SCOOL05
- * workshop. Available at: http://hdl.handle.net/1802/2104
+ * Because we use expiration for arena size control, we cannot
+ * throw TimeoutExceptions in the timed version of the public
+ * exchange method until the arena size has shrunken to zero (or
+ * the arena isn't enabled). This may delay response to timeout
+ * but is still within spec.
+ *
+ * Essentially all of the implementation is in methods
+ * slotExchange and arenaExchange. These have similar overall
+ * structure, but differ in too many details to combine. The
+ * slotExchange method uses the single Exchanger field "slot"
+ * rather than arena array elements. However, it still needs
+ * minimal collision detection to trigger arena construction.
+ * (The messiest part is making sure interrupt status and
+ * InterruptedExceptions come out right during transitions when
+ * both methods may be called. This is done by using null return
+ * as a sentinel to recheck interrupt status.)
+ *
+ * As is too common in this sort of code, methods are monolithic
+ * because most of the logic relies on reads of fields that are
+ * maintained as local variables so can't be nicely factored --
+ * mainly, here, bulky spin->yield->block/cancel code), and
+ * heavily dependent on intrinsics (Unsafe) to use inlined
+ * embedded CAS and related memory access operations (that tend
+ * not to be as readily inlined by dynamic compilers when they are
+ * hidden behind other methods that would more nicely name and
+ * encapsulate the intended effects). This includes the use of
+ * putOrderedX to clear fields of the per-thread Nodes between
+ * uses. Note that field Node.item is not declared as volatile
+ * even though it is read by releasing threads, because they only
+ * do so after CAS operations that must precede access, and all
+ * uses by the owning thread are otherwise acceptably ordered by
+ * other operations. (Because the actual points of atomicity are
+ * slot CASes, it would also be legal for the write to Node.match
+ * in a release to be weaker than a full volatile write. However,
+ * this is not done because it could allow further postponement of
+ * the write, delaying progress.)
*/
+ /**
+ * The byte distance (as a shift value) between any two used slots
+ * in the arena. 1 << ASHIFT should be at least cacheline size.
+ */
+ private static final int ASHIFT = 7;
+
+ /**
+ * The maximum supported arena index. The maximum allocatable
+ * arena size is MMASK + 1. Must be a power of two minus one, less
+ * than (1<<(31-ASHIFT)). The cap of 255 (0xff) more than suffices
+ * for the expected scaling limits of the main algorithms.
+ */
+ private static final int MMASK = 0xff;
+
+ /**
+ * Unit for sequence/version bits of bound field. Each successful
+ * change to the bound also adds SEQ.
+ */
+ private static final int SEQ = MMASK + 1;
+
/** The number of CPUs, for sizing and spin control */
private static final int NCPU = Runtime.getRuntime().availableProcessors();
/**
- * The capacity of the arena. Set to a value that provides more
- * than enough space to handle contention. On small machines
- * most slots won't be used, but it is still not wasted because
- * the extra space provides some machine-level address padding
- * to minimize interference with heavily CAS'ed Slot locations.
- * And on very large machines, performance eventually becomes
- * bounded by memory bandwidth, not numbers of threads/CPUs.
- * This constant cannot be changed without also modifying
- * indexing and hashing algorithms.
+ * The maximum slot index of the arena: The number of slots that
+ * can in principle hold all threads without contention, or at
+ * most the maximum indexable value.
*/
- private static final int CAPACITY = 32;
+ static final int FULL = (NCPU >= (MMASK << 1)) ? MMASK : NCPU >>> 1;
/**
- * The value of "max" that will hold all threads without
- * contention. When this value is less than CAPACITY, some
- * otherwise wasted expansion can be avoided.
+ * The bound for spins while waiting for a match. The actual
+ * number of iterations will on average be about twice this value
+ * due to randomization. Note: Spinning is disabled when NCPU==1.
*/
- private static final int FULL =
- Math.max(0, Math.min(CAPACITY, NCPU / 2) - 1);
-
- /**
- * The number of times to spin (doing nothing except polling a
- * memory location) before blocking or giving up while waiting to
- * be fulfilled. Should be zero on uniprocessors. On
- * multiprocessors, this value should be large enough so that two
- * threads exchanging items as fast as possible block only when
- * one of them is stalled (due to GC or preemption), but not much
- * longer, to avoid wasting CPU resources. Seen differently, this
- * value is a little over half the number of cycles of an average
- * context switch time on most systems. The value here is
- * approximately the average of those across a range of tested
- * systems.
- */
- private static final int SPINS = (NCPU == 1) ? 0 : 2000;
-
- /**
- * The number of times to spin before blocking in timed waits.
- * Timed waits spin more slowly because checking the time takes
- * time. The best value relies mainly on the relative rate of
- * System.nanoTime vs memory accesses. The value is empirically
- * derived to work well across a variety of systems.
- */
- private static final int TIMED_SPINS = SPINS / 20;
-
- /**
- * Sentinel item representing cancellation of a wait due to
- * interruption, timeout, or elapsed spin-waits. This value is
- * placed in holes on cancellation, and used as a return value
- * from waiting methods to indicate failure to set or get hole.
- */
- private static final Object CANCEL = new Object();
+ private static final int SPINS = 1 << 10;
/**
* Value representing null arguments/returns from public
- * methods. This disambiguates from internal requirement that
- * holes start out as null to mean they are not yet set.
+ * methods. Needed because the API originally didn't disallow null
+ * arguments, which it should have.
*/
private static final Object NULL_ITEM = new Object();
/**
- * Nodes hold partially exchanged data. This class
- * opportunistically subclasses AtomicReference to represent the
- * hole. So get() returns hole, and compareAndSet CAS'es value
- * into hole. This class cannot be parameterized as "V" because
- * of the use of non-V CANCEL sentinels.
+ * Sentinel value returned by internal exchange methods upon
+ * timeout, to avoid need for separate timed versions of these
+ * methods.
*/
- private static final class Node extends AtomicReference<Object> {
- /** The element offered by the Thread creating this node. */
- public final Object item;
+ private static final Object TIMED_OUT = new Object();
- /** The Thread waiting to be signalled; null until waiting. */
- public volatile Thread waiter;
+ /**
+ * Nodes hold partially exchanged data, plus other per-thread
+ * bookkeeping.
+ */
+ static final class Node {
+ int index; // Arena index
+ int bound; // Last recorded value of Exchanger.bound
+ int collides; // Number of CAS failures at current bound
+ int hash; // Pseudo-random for spins
+ Object item; // This thread's current item
+ volatile Object match; // Item provided by releasing thread
+ volatile Thread parked; // Set to this thread when parked, else null
- /**
- * Creates node with given item and empty hole.
- * @param item the item
- */
- public Node(Object item) {
- this.item = item;
- }
+ // Padding to ameliorate unfortunate memory placements
+ Object p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, pa, pb, pc, pd, pe, pf;
+ Object q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe, qf;
+ }
+
+ /** The corresponding thread local class */
+ static final class Participant extends ThreadLocal<Node> {
+ public Node initialValue() { return new Node(); }
}
/**
- * A Slot is an AtomicReference with heuristic padding to lessen
- * cache effects of this heavily CAS'ed location. While the
- * padding adds noticeable space, all slots are created only on
- * demand, and there will be more than one of them only when it
- * would improve throughput more than enough to outweigh using
- * extra space.
+ * Per-thread state
*/
- private static final class Slot extends AtomicReference<Object> {
- // Improve likelihood of isolation on <= 128 byte cache lines.
- // We used to target 64 byte cache lines, but some x86s (including
- // i7 under some BIOSes) actually use 128 byte cache lines.
- long q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, qa, qb, qc, qd, qe;
- }
+ private final Participant participant;
/**
- * Slot array. Elements are lazily initialized when needed.
- * Declared volatile to enable double-checked lazy construction.
+ * Elimination array; null until enabled (within slotExchange).
+ * Element accesses use emulation of volatile gets and CAS.
*/
- private volatile Slot[] arena = new Slot[CAPACITY];
+ private volatile Node[] arena;
/**
- * The maximum slot index being used. The value sometimes
- * increases when a thread experiences too many CAS contentions,
- * and sometimes decreases when a spin-wait elapses. Changes
- * are performed only via compareAndSet, to avoid stale values
- * when a thread happens to stall right before setting.
+ * Slot used until contention detected.
*/
- private final AtomicInteger max = new AtomicInteger();
+ private volatile Node slot;
/**
- * Main exchange function, handling the different policy variants.
- * Uses Object, not "V" as argument and return value to simplify
- * handling of sentinel values. Callers from public methods decode
- * and cast accordingly.
+ * The index of the largest valid arena position, OR'ed with SEQ
+ * number in high bits, incremented on each update. The initial
+ * update from 0 to SEQ is used to ensure that the arena array is
+ * constructed only once.
+ */
+ private volatile int bound;
+
+ /**
+ * Exchange function when arenas enabled. See above for explanation.
*
* @param item the (non-null) item to exchange
* @param timed true if the wait is timed
- * @param nanos if timed, the maximum wait time
- * @return the other thread's item, or CANCEL if interrupted or timed out
+ * @param ns if timed, the maximum wait time, else 0L
+ * @return the other thread's item; or null if interrupted; or
+ * TIMED_OUT if timed and timed out
*/
- private Object doExchange(Object item, boolean timed, long nanos) {
- Node me = new Node(item); // Create in case occupying
- int index = hashIndex(); // Index of current slot
- int fails = 0; // Number of CAS failures
-
- for (;;) {
- Object y; // Contents of current slot
- Slot slot = arena[index];
- if (slot == null) // Lazily initialize slots
- createSlot(index); // Continue loop to reread
- else if ((y = slot.get()) != null && // Try to fulfill
- slot.compareAndSet(y, null)) {
- Node you = (Node)y; // Transfer item
- if (you.compareAndSet(null, item)) {
- LockSupport.unpark(you.waiter);
- return you.item;
- } // Else cancelled; continue
- }
- else if (y == null && // Try to occupy
- slot.compareAndSet(null, me)) {
- if (index == 0) // Blocking wait for slot 0
- return timed ?
- awaitNanos(me, slot, nanos) :
- await(me, slot);
- Object v = spinWait(me, slot); // Spin wait for non-0
- if (v != CANCEL)
- return v;
- me = new Node(item); // Throw away cancelled node
- int m = max.get();
- if (m > (index >>>= 1)) // Decrease index
- max.compareAndSet(m, m - 1); // Maybe shrink table
- }
- else if (++fails > 1) { // Allow 2 fails on 1st slot
- int m = max.get();
- if (fails > 3 && m < FULL && max.compareAndSet(m, m + 1))
- index = m + 1; // Grow on 3rd failed slot
- else if (--index < 0)
- index = m; // Circularly traverse
- }
- }
- }
-
- /**
- * Returns a hash index for the current thread. Uses a one-step
- * FNV-1a hash code (http://www.isthe.com/chongo/tech/comp/fnv/)
- * based on the current thread's Thread.getId(). These hash codes
- * have more uniform distribution properties with respect to small
- * moduli (here 1-31) than do other simple hashing functions.
- *
- * <p>To return an index between 0 and max, we use a cheap
- * approximation to a mod operation, that also corrects for bias
- * due to non-power-of-2 remaindering (see {@link
- * java.util.Random#nextInt}). Bits of the hashcode are masked
- * with "nbits", the ceiling power of two of table size (looked up
- * in a table packed into three ints). If too large, this is
- * retried after rotating the hash by nbits bits, while forcing new
- * top bit to 0, which guarantees eventual termination (although
- * with a non-random-bias). This requires an average of less than
- * 2 tries for all table sizes, and has a maximum 2% difference
- * from perfectly uniform slot probabilities when applied to all
- * possible hash codes for sizes less than 32.
- *
- * @return a per-thread-random index, 0 <= index < max
- */
- private final int hashIndex() {
- long id = Thread.currentThread().getId();
- int hash = (((int)(id ^ (id >>> 32))) ^ 0x811c9dc5) * 0x01000193;
-
- int m = max.get();
- int nbits = (((0xfffffc00 >> m) & 4) | // Compute ceil(log2(m+1))
- ((0x000001f8 >>> m) & 2) | // The constants hold
- ((0xffff00f2 >>> m) & 1)); // a lookup table
- int index;
- while ((index = hash & ((1 << nbits) - 1)) > m) // May retry on
- hash = (hash >>> nbits) | (hash << (33 - nbits)); // non-power-2 m
- return index;
- }
-
- /**
- * Creates a new slot at given index. Called only when the slot
- * appears to be null. Relies on double-check using builtin
- * locks, since they rarely contend. This in turn relies on the
- * arena array being declared volatile.
- *
- * @param index the index to add slot at
- */
- private void createSlot(int index) {
- // Create slot outside of lock to narrow sync region
- Slot newSlot = new Slot();
- Slot[] a = arena;
- synchronized (a) {
- if (a[index] == null)
- a[index] = newSlot;
- }
- }
-
- /**
- * Tries to cancel a wait for the given node waiting in the given
- * slot, if so, helping clear the node from its slot to avoid
- * garbage retention.
- *
- * @param node the waiting node
- * @param slot the slot it is waiting in
- * @return true if successfully cancelled
- */
- private static boolean tryCancel(Node node, Slot slot) {
- if (!node.compareAndSet(null, CANCEL))
- return false;
- if (slot.get() == node) // pre-check to minimize contention
- slot.compareAndSet(node, null);
- return true;
- }
-
- // Three forms of waiting. Each just different enough not to merge
- // code with others.
-
- /**
- * Spin-waits for hole for a non-0 slot. Fails if spin elapses
- * before hole filled. Does not check interrupt, relying on check
- * in public exchange method to abort if interrupted on entry.
- *
- * @param node the waiting node
- * @return on success, the hole; on failure, CANCEL
- */
- private static Object spinWait(Node node, Slot slot) {
- int spins = SPINS;
- for (;;) {
- Object v = node.get();
- if (v != null)
+ private final Object arenaExchange(Object item, boolean timed, long ns) {
+ Node[] a = arena;
+ Node p = participant.get();
+ for (int i = p.index;;) { // access slot at i
+ int b, m, c; long j; // j is raw array offset
+ Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
+ if (q != null && U.compareAndSwapObject(a, j, q, null)) {
+ Object v = q.item; // release
+ q.match = item;
+ Thread w = q.parked;
+ if (w != null)
+ U.unpark(w);
return v;
- else if (spins > 0)
- --spins;
- else
- tryCancel(node, slot);
- }
- }
-
- /**
- * Waits for (by spinning and/or blocking) and gets the hole
- * filled in by another thread. Fails if interrupted before
- * hole filled.
- *
- * When a node/thread is about to block, it sets its waiter field
- * and then rechecks state at least one more time before actually
- * parking, thus covering race vs fulfiller noticing that waiter
- * is non-null so should be woken.
- *
- * Thread interruption status is checked only surrounding calls to
- * park. The caller is assumed to have checked interrupt status
- * on entry.
- *
- * @param node the waiting node
- * @return on success, the hole; on failure, CANCEL
- */
- private static Object await(Node node, Slot slot) {
- Thread w = Thread.currentThread();
- int spins = SPINS;
- for (;;) {
- Object v = node.get();
- if (v != null)
- return v;
- else if (spins > 0) // Spin-wait phase
- --spins;
- else if (node.waiter == null) // Set up to block next
- node.waiter = w;
- else if (w.isInterrupted()) // Abort on interrupt
- tryCancel(node, slot);
- else // Block
- LockSupport.park(node);
- }
- }
-
- /**
- * Waits for (at index 0) and gets the hole filled in by another
- * thread. Fails if timed out or interrupted before hole filled.
- * Same basic logic as untimed version, but a bit messier.
- *
- * @param node the waiting node
- * @param nanos the wait time
- * @return on success, the hole; on failure, CANCEL
- */
- private Object awaitNanos(Node node, Slot slot, long nanos) {
- int spins = TIMED_SPINS;
- long lastTime = 0;
- Thread w = null;
- for (;;) {
- Object v = node.get();
- if (v != null)
- return v;
- long now = System.nanoTime();
- if (w == null)
- w = Thread.currentThread();
- else
- nanos -= now - lastTime;
- lastTime = now;
- if (nanos > 0) {
- if (spins > 0)
- --spins;
- else if (node.waiter == null)
- node.waiter = w;
- else if (w.isInterrupted())
- tryCancel(node, slot);
- else
- LockSupport.parkNanos(node, nanos);
}
- else if (tryCancel(node, slot) && !w.isInterrupted())
- return scanOnTimeout(node);
- }
- }
-
- /**
- * Sweeps through arena checking for any waiting threads. Called
- * only upon return from timeout while waiting in slot 0. When a
- * thread gives up on a timed wait, it is possible that a
- * previously-entered thread is still waiting in some other
- * slot. So we scan to check for any. This is almost always
- * overkill, but decreases the likelihood of timeouts when there
- * are other threads present to far less than that in lock-based
- * exchangers in which earlier-arriving threads may still be
- * waiting on entry locks.
- *
- * @param node the waiting node
- * @return another thread's item, or CANCEL
- */
- private Object scanOnTimeout(Node node) {
- Object y;
- for (int j = arena.length - 1; j >= 0; --j) {
- Slot slot = arena[j];
- if (slot != null) {
- while ((y = slot.get()) != null) {
- if (slot.compareAndSet(y, null)) {
- Node you = (Node)y;
- if (you.compareAndSet(null, node.item)) {
- LockSupport.unpark(you.waiter);
- return you.item;
+ else if (i <= (m = (b = bound) & MMASK) && q == null) {
+ p.item = item; // offer
+ if (U.compareAndSwapObject(a, j, null, p)) {
+ long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
+ Thread t = Thread.currentThread(); // wait
+ for (int h = p.hash, spins = SPINS;;) {
+ Object v = p.match;
+ if (v != null) {
+ U.putOrderedObject(p, MATCH, null);
+ p.item = null; // clear for next use
+ p.hash = h;
+ return v;
+ }
+ else if (spins > 0) {
+ h ^= h << 1; h ^= h >>> 3; h ^= h << 10; // xorshift
+ if (h == 0) // initialize hash
+ h = SPINS | (int)t.getId();
+ else if (h < 0 && // approx 50% true
+ (--spins & ((SPINS >>> 1) - 1)) == 0)
+ Thread.yield(); // two yields per wait
+ }
+ else if (U.getObjectVolatile(a, j) != p)
+ spins = SPINS; // releaser hasn't set match yet
+ else if (!t.isInterrupted() && m == 0 &&
+ (!timed ||
+ (ns = end - System.nanoTime()) > 0L)) {
+ U.putObject(t, BLOCKER, this); // emulate LockSupport
+ p.parked = t; // minimize window
+ if (U.getObjectVolatile(a, j) == p)
+ U.park(false, ns);
+ p.parked = null;
+ U.putObject(t, BLOCKER, null);
+ }
+ else if (U.getObjectVolatile(a, j) == p &&
+ U.compareAndSwapObject(a, j, p, null)) {
+ if (m != 0) // try to shrink
+ U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
+ p.item = null;
+ p.hash = h;
+ i = p.index >>>= 1; // descend
+ if (Thread.interrupted())
+ return null;
+ if (timed && m == 0 && ns <= 0L)
+ return TIMED_OUT;
+ break; // expired; restart
}
}
}
+ else
+ p.item = null; // clear offer
+ }
+ else {
+ if (p.bound != b) { // stale; reset
+ p.bound = b;
+ p.collides = 0;
+ i = (i != m || m == 0) ? m : m - 1;
+ }
+ else if ((c = p.collides) < m || m == FULL ||
+ !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
+ p.collides = c + 1;
+ i = (i == 0) ? m : i - 1; // cyclically traverse
+ }
+ else
+ i = m + 1; // grow
+ p.index = i;
}
}
- return CANCEL;
+ }
+
+ /**
+ * Exchange function used until arenas enabled. See above for explanation.
+ *
+ * @param item the item to exchange
+ * @param timed true if the wait is timed
+ * @param ns if timed, the maximum wait time, else 0L
+ * @return the other thread's item; or null if either the arena
+ * was enabled or the thread was interrupted before completion; or
+ * TIMED_OUT if timed and timed out
+ */
+ private final Object slotExchange(Object item, boolean timed, long ns) {
+ Node p = participant.get();
+ Thread t = Thread.currentThread();
+ if (t.isInterrupted()) // preserve interrupt status so caller can recheck
+ return null;
+
+ for (Node q;;) {
+ if ((q = slot) != null) {
+ if (U.compareAndSwapObject(this, SLOT, q, null)) {
+ Object v = q.item;
+ q.match = item;
+ Thread w = q.parked;
+ if (w != null)
+ U.unpark(w);
+ return v;
+ }
+ // create arena on contention, but continue until slot null
+ if (NCPU > 1 && bound == 0 &&
+ U.compareAndSwapInt(this, BOUND, 0, SEQ))
+ arena = new Node[(FULL + 2) << ASHIFT];
+ }
+ else if (arena != null)
+ return null; // caller must reroute to arenaExchange
+ else {
+ p.item = item;
+ if (U.compareAndSwapObject(this, SLOT, null, p))
+ break;
+ p.item = null;
+ }
+ }
+
+ // await release
+ int h = p.hash;
+ long end = timed ? System.nanoTime() + ns : 0L;
+ int spins = (NCPU > 1) ? SPINS : 1;
+ Object v;
+ while ((v = p.match) == null) {
+ if (spins > 0) {
+ h ^= h << 1; h ^= h >>> 3; h ^= h << 10;
+ if (h == 0)
+ h = SPINS | (int)t.getId();
+ else if (h < 0 && (--spins & ((SPINS >>> 1) - 1)) == 0)
+ Thread.yield();
+ }
+ else if (slot != p)
+ spins = SPINS;
+ else if (!t.isInterrupted() && arena == null &&
+ (!timed || (ns = end - System.nanoTime()) > 0L)) {
+ U.putObject(t, BLOCKER, this);
+ p.parked = t;
+ if (slot == p)
+ U.park(false, ns);
+ p.parked = null;
+ U.putObject(t, BLOCKER, null);
+ }
+ else if (U.compareAndSwapObject(this, SLOT, p, null)) {
+ v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
+ break;
+ }
+ }
+ U.putOrderedObject(p, MATCH, null);
+ p.item = null;
+ p.hash = h;
+ return v;
}
/**
* Creates a new Exchanger.
*/
public Exchanger() {
+ participant = new Participant();
}
/**
@@ -588,16 +530,16 @@
* @throws InterruptedException if the current thread was
* interrupted while waiting
*/
+ @SuppressWarnings("unchecked")
public V exchange(V x) throws InterruptedException {
- if (!Thread.interrupted()) {
- Object v = doExchange((x == null) ? NULL_ITEM : x, false, 0);
- if (v == NULL_ITEM)
- return null;
- if (v != CANCEL)
- return (V)v;
- Thread.interrupted(); // Clear interrupt status on IE throw
- }
- throw new InterruptedException();
+ Object v;
+ Object item = (x == null) ? NULL_ITEM : x; // translate null args
+ if ((arena != null ||
+ (v = slotExchange(item, false, 0L)) == null) &&
+ ((Thread.interrupted() || // disambiguates null return
+ (v = arenaExchange(item, false, 0L)) == null)))
+ throw new InterruptedException();
+ return (v == NULL_ITEM) ? null : (V)v;
}
/**
@@ -635,25 +577,61 @@
*
* @param x the object to exchange
* @param timeout the maximum time to wait
- * @param unit the time unit of the <tt>timeout</tt> argument
+ * @param unit the time unit of the {@code timeout} argument
* @return the object provided by the other thread
* @throws InterruptedException if the current thread was
* interrupted while waiting
* @throws TimeoutException if the specified waiting time elapses
* before another thread enters the exchange
*/
+ @SuppressWarnings("unchecked")
public V exchange(V x, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
- if (!Thread.interrupted()) {
- Object v = doExchange((x == null) ? NULL_ITEM : x,
- true, unit.toNanos(timeout));
- if (v == NULL_ITEM)
- return null;
- if (v != CANCEL)
- return (V)v;
- if (!Thread.interrupted())
- throw new TimeoutException();
- }
- throw new InterruptedException();
+ Object v;
+ Object item = (x == null) ? NULL_ITEM : x;
+ long ns = unit.toNanos(timeout);
+ if ((arena != null ||
+ (v = slotExchange(item, true, ns)) == null) &&
+ ((Thread.interrupted() ||
+ (v = arenaExchange(item, true, ns)) == null)))
+ throw new InterruptedException();
+ if (v == TIMED_OUT)
+ throw new TimeoutException();
+ return (v == NULL_ITEM) ? null : (V)v;
}
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe U;
+ private static final long BOUND;
+ private static final long SLOT;
+ private static final long MATCH;
+ private static final long BLOCKER;
+ private static final int ABASE;
+ static {
+ int s;
+ try {
+ U = sun.misc.Unsafe.getUnsafe();
+ Class<?> ek = Exchanger.class;
+ Class<?> nk = Node.class;
+ Class<?> ak = Node[].class;
+ Class<?> tk = Thread.class;
+ BOUND = U.objectFieldOffset
+ (ek.getDeclaredField("bound"));
+ SLOT = U.objectFieldOffset
+ (ek.getDeclaredField("slot"));
+ MATCH = U.objectFieldOffset
+ (nk.getDeclaredField("match"));
+ BLOCKER = U.objectFieldOffset
+ (tk.getDeclaredField("parkBlocker"));
+ s = U.arrayIndexScale(ak);
+ // ABASE absorbs padding in front of element 0
+ ABASE = U.arrayBaseOffset(ak) + (1 << ASHIFT);
+
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ if ((s & (s-1)) != 0 || s > (1 << ASHIFT))
+ throw new Error("Unsupported array scale");
+ }
+
}
diff --git a/luni/src/main/java/java/util/concurrent/ExecutionException.java b/luni/src/main/java/java/util/concurrent/ExecutionException.java
index 9bb8dee..dbfbe65 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutionException.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutionException.java
@@ -19,14 +19,14 @@
private static final long serialVersionUID = 7830266012832686185L;
/**
- * Constructs an <tt>ExecutionException</tt> with no detail message.
+ * Constructs an {@code ExecutionException} with no detail message.
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
protected ExecutionException() { }
/**
- * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * Constructs an {@code ExecutionException} with the specified detail
* message. The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*
@@ -37,7 +37,7 @@
}
/**
- * Constructs an <tt>ExecutionException</tt> with the specified detail
+ * Constructs an {@code ExecutionException} with the specified detail
* message and cause.
*
* @param message the detail message
@@ -49,10 +49,10 @@
}
/**
- * Constructs an <tt>ExecutionException</tt> with the specified cause.
+ * Constructs an {@code ExecutionException} with the specified cause.
* The detail message is set to {@code (cause == null ? null :
* cause.toString())} (which typically contains the class and
- * detail message of <tt>cause</tt>).
+ * detail message of {@code cause}).
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method)
diff --git a/luni/src/main/java/java/util/concurrent/Executor.java b/luni/src/main/java/java/util/concurrent/Executor.java
index 831bf46..f55209a 100644
--- a/luni/src/main/java/java/util/concurrent/Executor.java
+++ b/luni/src/main/java/java/util/concurrent/Executor.java
@@ -10,9 +10,9 @@
* An object that executes submitted {@link Runnable} tasks. This
* interface provides a way of decoupling task submission from the
* mechanics of how each task will be run, including details of thread
- * use, scheduling, etc. An <tt>Executor</tt> is normally used
+ * use, scheduling, etc. An {@code Executor} is normally used
* instead of explicitly creating threads. For example, rather than
- * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
+ * invoking {@code new Thread(new(RunnableTask())).start()} for each
* of a set of tasks, you might use:
*
* <pre>
@@ -22,7 +22,7 @@
* ...
* </pre>
*
- * However, the <tt>Executor</tt> interface does not strictly
+ * However, the {@code Executor} interface does not strictly
* require that execution be asynchronous. In the simplest case, an
* executor can run the submitted task immediately in the caller's
* thread:
@@ -45,7 +45,7 @@
* }
* }}</pre>
*
- * Many <tt>Executor</tt> implementations impose some sort of
+ * Many {@code Executor} implementations impose some sort of
* limitation on how and when tasks are scheduled. The executor below
* serializes the submission of tasks to a second executor,
* illustrating a composite executor.
@@ -82,7 +82,7 @@
* }
* }}</pre>
*
- * The <tt>Executor</tt> implementations provided in this package
+ * The {@code Executor} implementations provided in this package
* implement {@link ExecutorService}, which is a more extensive
* interface. The {@link ThreadPoolExecutor} class provides an
* extensible thread pool implementation. The {@link Executors} class
@@ -101,11 +101,11 @@
/**
* Executes the given command at some time in the future. The command
* may execute in a new thread, in a pooled thread, or in the calling
- * thread, at the discretion of the <tt>Executor</tt> implementation.
+ * thread, at the discretion of the {@code Executor} implementation.
*
* @param command the runnable task
* @throws RejectedExecutionException if this task cannot be
- * accepted for execution.
+ * accepted for execution
* @throws NullPointerException if command is null
*/
void execute(Runnable command);
diff --git a/luni/src/main/java/java/util/concurrent/ExecutorService.java b/luni/src/main/java/java/util/concurrent/ExecutorService.java
index a33ceec..4599f59 100644
--- a/luni/src/main/java/java/util/concurrent/ExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ExecutorService.java
@@ -17,21 +17,21 @@
* methods that can produce a {@link Future} for tracking progress of
* one or more asynchronous tasks.
*
- * <p> An <tt>ExecutorService</tt> can be shut down, which will cause
+ * <p>An {@code ExecutorService} can be shut down, which will cause
* it to reject new tasks. Two different methods are provided for
- * shutting down an <tt>ExecutorService</tt>. The {@link #shutdown}
+ * shutting down an {@code ExecutorService}. The {@link #shutdown}
* method will allow previously submitted tasks to execute before
* terminating, while the {@link #shutdownNow} method prevents waiting
* tasks from starting and attempts to stop currently executing tasks.
* Upon termination, an executor has no tasks actively executing, no
* tasks awaiting execution, and no new tasks can be submitted. An
- * unused <tt>ExecutorService</tt> should be shut down to allow
+ * unused {@code ExecutorService} should be shut down to allow
* reclamation of its resources.
*
- * <p> Method <tt>submit</tt> extends base method {@link
+ * <p>Method {@code submit} extends base method {@link
* Executor#execute} by creating and returning a {@link Future} that
* can be used to cancel execution and/or wait for completion.
- * Methods <tt>invokeAny</tt> and <tt>invokeAll</tt> perform the most
+ * Methods {@code invokeAny} and {@code invokeAll} perform the most
* commonly useful forms of bulk execution, executing a collection of
* tasks and then waiting for at least one, or all, to
* complete. (Class {@link ExecutorCompletionService} can be used to
@@ -76,9 +76,9 @@
* }
* }}</pre>
*
- * The following method shuts down an <tt>ExecutorService</tt> in two phases,
- * first by calling <tt>shutdown</tt> to reject incoming tasks, and then
- * calling <tt>shutdownNow</tt>, if necessary, to cancel any lingering tasks:
+ * The following method shuts down an {@code ExecutorService} in two phases,
+ * first by calling {@code shutdown} to reject incoming tasks, and then
+ * calling {@code shutdownNow}, if necessary, to cancel any lingering tasks:
*
* <pre> {@code
* void shutdownAndAwaitTermination(ExecutorService pool) {
@@ -141,18 +141,18 @@
List<Runnable> shutdownNow();
/**
- * Returns <tt>true</tt> if this executor has been shut down.
+ * Returns {@code true} if this executor has been shut down.
*
- * @return <tt>true</tt> if this executor has been shut down
+ * @return {@code true} if this executor has been shut down
*/
boolean isShutdown();
/**
- * Returns <tt>true</tt> if all tasks have completed following shut down.
- * Note that <tt>isTerminated</tt> is never <tt>true</tt> unless
- * either <tt>shutdown</tt> or <tt>shutdownNow</tt> was called first.
+ * Returns {@code true} if all tasks have completed following shut down.
+ * Note that {@code isTerminated} is never {@code true} unless
+ * either {@code shutdown} or {@code shutdownNow} was called first.
*
- * @return <tt>true</tt> if all tasks have completed following shut down
+ * @return {@code true} if all tasks have completed following shut down
*/
boolean isTerminated();
@@ -163,26 +163,25 @@
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
- * @return <tt>true</tt> if this executor terminated and
- * <tt>false</tt> if the timeout elapsed before termination
+ * @return {@code true} if this executor terminated and
+ * {@code false} if the timeout elapsed before termination
* @throws InterruptedException if interrupted while waiting
*/
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
-
/**
* Submits a value-returning task for execution and returns a
* Future representing the pending results of the task. The
- * Future's <tt>get</tt> method will return the task's result upon
+ * Future's {@code get} method will return the task's result upon
* successful completion.
*
* <p>
* If you would like to immediately block waiting
* for a task, you can use constructions of the form
- * <tt>result = exec.submit(aCallable).get();</tt>
+ * {@code result = exec.submit(aCallable).get();}
*
- * <p> Note: The {@link Executors} class includes a set of methods
+ * <p>Note: The {@link Executors} class includes a set of methods
* that can convert some other common closure-like objects,
* for example, {@link java.security.PrivilegedAction} to
* {@link Callable} form so they can be submitted.
@@ -197,7 +196,7 @@
/**
* Submits a Runnable task for execution and returns a Future
- * representing that task. The Future's <tt>get</tt> method will
+ * representing that task. The Future's {@code get} method will
* return the given result upon successful completion.
*
* @param task the task to submit
@@ -211,8 +210,8 @@
/**
* Submits a Runnable task for execution and returns a Future
- * representing that task. The Future's <tt>get</tt> method will
- * return <tt>null</tt> upon <em>successful</em> completion.
+ * representing that task. The Future's {@code get} method will
+ * return {@code null} upon <em>successful</em> completion.
*
* @param task the task to submit
* @return a Future representing pending completion of the task
@@ -225,7 +224,7 @@
/**
* Executes the given tasks, returning a list of Futures holding
* their status and results when all complete.
- * {@link Future#isDone} is <tt>true</tt> for each
+ * {@link Future#isDone} is {@code true} for each
* element of the returned list.
* Note that a <em>completed</em> task could have
* terminated either normally or by throwing an exception.
@@ -233,16 +232,15 @@
* collection is modified while this operation is in progress.
*
* @param tasks the collection of tasks
- * @return A list of Futures representing the tasks, in the same
+ * @return a list of Futures representing the tasks, in the same
* sequential order as produced by the iterator for the
- * given task list, each of which has completed.
+ * given task list, each of which has completed
* @throws InterruptedException if interrupted while waiting, in
- * which case unfinished tasks are cancelled.
- * @throws NullPointerException if tasks or any of its elements are <tt>null</tt>
+ * which case unfinished tasks are cancelled
+ * @throws NullPointerException if tasks or any of its elements are {@code null}
* @throws RejectedExecutionException if any task cannot be
* scheduled for execution
*/
-
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
@@ -250,7 +248,7 @@
* Executes the given tasks, returning a list of Futures holding
* their status and results
* when all complete or the timeout expires, whichever happens first.
- * {@link Future#isDone} is <tt>true</tt> for each
+ * {@link Future#isDone} is {@code true} for each
* element of the returned list.
* Upon return, tasks that have not completed are cancelled.
* Note that a <em>completed</em> task could have
@@ -269,7 +267,7 @@
* @throws InterruptedException if interrupted while waiting, in
* which case unfinished tasks are cancelled
* @throws NullPointerException if tasks, any of its elements, or
- * unit are <tt>null</tt>
+ * unit are {@code null}
* @throws RejectedExecutionException if any task cannot be scheduled
* for execution
*/
@@ -289,7 +287,7 @@
* @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks or any element task
- * subject to execution is <tt>null</tt>
+ * subject to execution is {@code null}
* @throws IllegalArgumentException if tasks is empty
* @throws ExecutionException if no task successfully completes
* @throws RejectedExecutionException if tasks cannot be scheduled
@@ -310,10 +308,10 @@
* @param tasks the collection of tasks
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
- * @return the result returned by one of the tasks.
+ * @return the result returned by one of the tasks
* @throws InterruptedException if interrupted while waiting
* @throws NullPointerException if tasks, or unit, or any element
- * task subject to execution is <tt>null</tt>
+ * task subject to execution is {@code null}
* @throws TimeoutException if the given timeout elapses before
* any task successfully completes
* @throws ExecutionException if no task successfully completes
diff --git a/luni/src/main/java/java/util/concurrent/Executors.java b/luni/src/main/java/java/util/concurrent/Executors.java
index b4f03ba..53c68fc 100644
--- a/luni/src/main/java/java/util/concurrent/Executors.java
+++ b/luni/src/main/java/java/util/concurrent/Executors.java
@@ -34,7 +34,7 @@
* that sets newly created threads to a known state.
* <li> Methods that create and return a {@link Callable}
* out of other closure-like forms, so they can be used
- * in execution methods requiring <tt>Callable</tt>.
+ * in execution methods requiring {@code Callable}.
* </ul>
*
* @since 1.5
@@ -45,7 +45,7 @@
/**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue. At any point, at most
- * <tt>nThreads</tt> threads will be active processing tasks.
+ * {@code nThreads} threads will be active processing tasks.
* If additional tasks are submitted when all threads are active,
* they will wait in the queue until a thread is available.
* If any thread terminates due to a failure during execution
@@ -64,10 +64,48 @@
}
/**
+ * Creates a thread pool that maintains enough threads to support
+ * the given parallelism level, and may use multiple queues to
+ * reduce contention. The parallelism level corresponds to the
+ * maximum number of threads actively engaged in, or available to
+ * engage in, task processing. The actual number of threads may
+ * grow and shrink dynamically. A work-stealing pool makes no
+ * guarantees about the order in which submitted tasks are
+ * executed.
+ *
+ * @param parallelism the targeted parallelism level
+ * @return the newly created thread pool
+ * @throws IllegalArgumentException if {@code parallelism <= 0}
+ * @since 1.8
+ * @hide
+ */
+ public static ExecutorService newWorkStealingPool(int parallelism) {
+ return new ForkJoinPool
+ (parallelism,
+ ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+ null, true);
+ }
+
+ /**
+ * Creates a work-stealing thread pool using all
+ * {@link Runtime#availableProcessors available processors}
+ * as its target parallelism level.
+ * @return the newly created thread pool
+ * @since 1.8
+ * @hide
+ */
+ public static ExecutorService newWorkStealingPool() {
+ return new ForkJoinPool
+ (Runtime.getRuntime().availableProcessors(),
+ ForkJoinPool.defaultForkJoinWorkerThreadFactory,
+ null, true);
+ }
+
+ /**
* Creates a thread pool that reuses a fixed number of threads
* operating off a shared unbounded queue, using the provided
* ThreadFactory to create new threads when needed. At any point,
- * at most <tt>nThreads</tt> threads will be active processing
+ * at most {@code nThreads} threads will be active processing
* tasks. If additional tasks are submitted when all threads are
* active, they will wait in the queue until a thread is
* available. If any thread terminates due to a failure during
@@ -97,7 +135,7 @@
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
- * <tt>newFixedThreadPool(1)</tt> the returned executor is
+ * {@code newFixedThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
*
* @return the newly created single-threaded Executor
@@ -113,7 +151,7 @@
* Creates an Executor that uses a single worker thread operating
* off an unbounded queue, and uses the provided ThreadFactory to
* create a new thread when needed. Unlike the otherwise
- * equivalent <tt>newFixedThreadPool(1, threadFactory)</tt> the
+ * equivalent {@code newFixedThreadPool(1, threadFactory)} the
* returned executor is guaranteed not to be reconfigurable to use
* additional threads.
*
@@ -136,7 +174,7 @@
* will reuse previously constructed threads when they are
* available. These pools will typically improve the performance
* of programs that execute many short-lived asynchronous tasks.
- * Calls to <tt>execute</tt> will reuse previously constructed
+ * Calls to {@code execute} will reuse previously constructed
* threads if available. If no existing thread is available, a new
* thread will be created and added to the pool. Threads that have
* not been used for sixty seconds are terminated and removed from
@@ -178,7 +216,7 @@
* subsequent tasks.) Tasks are guaranteed to execute
* sequentially, and no more than one task will be active at any
* given time. Unlike the otherwise equivalent
- * <tt>newScheduledThreadPool(1)</tt> the returned executor is
+ * {@code newScheduledThreadPool(1)} the returned executor is
* guaranteed not to be reconfigurable to use additional threads.
* @return the newly created scheduled executor
*/
@@ -195,7 +233,7 @@
* place if needed to execute subsequent tasks.) Tasks are
* guaranteed to execute sequentially, and no more than one task
* will be active at any given time. Unlike the otherwise
- * equivalent <tt>newScheduledThreadPool(1, threadFactory)</tt>
+ * equivalent {@code newScheduledThreadPool(1, threadFactory)}
* the returned executor is guaranteed not to be reconfigurable to
* use additional threads.
* @param threadFactory the factory to use when creating new
@@ -212,7 +250,7 @@
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
- * even if they are idle.
+ * even if they are idle
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
*/
@@ -224,9 +262,9 @@
* Creates a thread pool that can schedule commands to run after a
* given delay, or to execute periodically.
* @param corePoolSize the number of threads to keep in the pool,
- * even if they are idle.
+ * even if they are idle
* @param threadFactory the factory to use when the executor
- * creates a new thread.
+ * creates a new thread
* @return a newly created scheduled thread pool
* @throws IllegalArgumentException if {@code corePoolSize < 0}
* @throws NullPointerException if threadFactory is null
@@ -236,7 +274,6 @@
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
-
/**
* Returns an object that delegates all defined {@link
* ExecutorService} methods to the given executor, but not any
@@ -244,7 +281,7 @@
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
- * @return an <tt>ExecutorService</tt> instance
+ * @return an {@code ExecutorService} instance
* @throws NullPointerException if executor null
*/
public static ExecutorService unconfigurableExecutorService(ExecutorService executor) {
@@ -260,7 +297,7 @@
* casts. This provides a way to safely "freeze" configuration and
* disallow tuning of a given concrete implementation.
* @param executor the underlying implementation
- * @return a <tt>ScheduledExecutorService</tt> instance
+ * @return a {@code ScheduledExecutorService} instance
* @throws NullPointerException if executor null
*/
public static ScheduledExecutorService unconfigurableScheduledExecutorService(ScheduledExecutorService executor) {
@@ -274,7 +311,7 @@
* This factory creates all new threads used by an Executor in the
* same {@link ThreadGroup}. Each new
* thread is created as a non-daemon thread with priority set to
- * the smaller of <tt>Thread.NORM_PRIORITY</tt> and the maximum
+ * the smaller of {@code Thread.NORM_PRIORITY} and the maximum
* priority permitted in the thread group. New threads have names
* accessible via {@link Thread#getName} of
* <em>pool-N-thread-M</em>, where <em>N</em> is the sequence
@@ -297,7 +334,7 @@
* Returns a {@link Callable} object that, when
* called, runs the given task and returns the given result. This
* can be useful when applying methods requiring a
- * <tt>Callable</tt> to an otherwise resultless action.
+ * {@code Callable} to an otherwise resultless action.
* @param task the task to run
* @param result the result to return
* @return a callable object
@@ -311,7 +348,7 @@
/**
* Returns a {@link Callable} object that, when
- * called, runs the given task and returns <tt>null</tt>.
+ * called, runs the given task and returns {@code null}.
* @param task the task to run
* @return a callable object
* @throws NullPointerException if task null
@@ -361,12 +398,7 @@
}
/**
- * Returns a {@link Callable} object that will, when
- * called, execute the given <tt>callable</tt> under the current
- * with the current context class loader as the context class loader.
- *
- * @return a callable object
- * @throws NullPointerException if callable null
+ * Legacy security code; do not use.
*/
public static <T> Callable<T> privilegedCallableUsingCurrentClassLoader(Callable<T> callable) {
if (callable == null)
@@ -451,18 +483,17 @@
return AccessController.doPrivileged(
new PrivilegedExceptionAction<T>() {
public T run() throws Exception {
- ClassLoader savedcl = null;
Thread t = Thread.currentThread();
- try {
- ClassLoader cl = t.getContextClassLoader();
- if (ccl != cl) {
- t.setContextClassLoader(ccl);
- savedcl = cl;
- }
+ ClassLoader cl = t.getContextClassLoader();
+ if (ccl == cl) {
return task.call();
- } finally {
- if (savedcl != null)
- t.setContextClassLoader(savedcl);
+ } else {
+ t.setContextClassLoader(ccl);
+ try {
+ return task.call();
+ } finally {
+ t.setContextClassLoader(cl);
+ }
}
}
}, acc);
@@ -609,21 +640,20 @@
super(executor);
e = executor;
}
- public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
+ public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
return e.schedule(command, delay, unit);
}
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
return e.schedule(callable, delay, unit);
}
- public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
+ public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
return e.scheduleAtFixedRate(command, initialDelay, period, unit);
}
- public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
+ public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
return e.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
}
-
/** Cannot instantiate. */
private Executors() {}
}
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
index ee15ac8..87ffff3 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinPool.java
@@ -11,7 +11,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import java.util.Random;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -19,15 +18,6 @@
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.locks.LockSupport;
-import java.util.concurrent.locks.ReentrantLock;
-import java.util.concurrent.locks.Condition;
-import libcore.util.SneakyThrow;
-
-// BEGIN android-note
-// removed security manager docs
-// END android-note
/**
* An {@link ExecutorService} for running {@link ForkJoinTask}s.
@@ -38,21 +28,31 @@
* <p>A {@code ForkJoinPool} differs from other kinds of {@link
* ExecutorService} mainly by virtue of employing
* <em>work-stealing</em>: all threads in the pool attempt to find and
- * execute subtasks created by other active tasks (eventually blocking
- * waiting for work if none exist). This enables efficient processing
- * when most tasks spawn other subtasks (as do most {@code
- * ForkJoinTask}s). When setting <em>asyncMode</em> to true in
- * constructors, {@code ForkJoinPool}s may also be appropriate for use
- * with event-style tasks that are never joined.
+ * execute tasks submitted to the pool and/or created by other active
+ * tasks (eventually blocking waiting for work if none exist). This
+ * enables efficient processing when most tasks spawn other subtasks
+ * (as do most {@code ForkJoinTask}s), as well as when many small
+ * tasks are submitted to the pool from external clients. Especially
+ * when setting <em>asyncMode</em> to true in constructors, {@code
+ * ForkJoinPool}s may also be appropriate for use with event-style
+ * tasks that are never joined.
*
- * <p>A {@code ForkJoinPool} is constructed with a given target
- * parallelism level; by default, equal to the number of available
- * processors. The pool attempts to maintain enough active (or
- * available) threads by dynamically adding, suspending, or resuming
- * internal worker threads, even if some tasks are stalled waiting to
- * join others. However, no such adjustments are guaranteed in the
- * face of blocked IO or other unmanaged synchronization. The nested
- * {@link ManagedBlocker} interface enables extension of the kinds of
+ * <p>A static {@link #commonPool()} is available and appropriate for
+ * most applications. The common pool is used by any ForkJoinTask that
+ * is not explicitly submitted to a specified pool. Using the common
+ * pool normally reduces resource usage (its threads are slowly
+ * reclaimed during periods of non-use, and reinstated upon subsequent
+ * use).
+ *
+ * <p>For applications that require separate or custom pools, a {@code
+ * ForkJoinPool} may be constructed with a given target parallelism
+ * level; by default, equal to the number of available processors. The
+ * pool attempts to maintain enough active (or available) threads by
+ * dynamically adding, suspending, or resuming internal worker
+ * threads, even if some tasks are stalled waiting to join
+ * others. However, no such adjustments are guaranteed in the face of
+ * blocked I/O or other unmanaged synchronization. The nested {@link
+ * ManagedBlocker} interface enables extension of the kinds of
* synchronization accommodated.
*
* <p>In addition to execution and lifecycle control methods, this
@@ -62,16 +62,17 @@
* {@link #toString} returns indications of pool state in a
* convenient form for informal monitoring.
*
- * <p> As is the case with other ExecutorServices, there are three
- * main task execution methods summarized in the following
- * table. These are designed to be used by clients not already engaged
- * in fork/join computations in the current pool. The main forms of
- * these methods accept instances of {@code ForkJoinTask}, but
- * overloaded forms also allow mixed execution of plain {@code
+ * <p>As is the case with other ExecutorServices, there are three
+ * main task execution methods summarized in the following table.
+ * These are designed to be used primarily by clients not already
+ * engaged in fork/join computations in the current pool. The main
+ * forms of these methods accept instances of {@code ForkJoinTask},
+ * but overloaded forms also allow mixed execution of plain {@code
* Runnable}- or {@code Callable}- based activities as well. However,
- * tasks that are already executing in a pool should normally
- * <em>NOT</em> use these pool execution methods, but instead use the
- * within-computation forms listed in the table.
+ * tasks that are already executing in a pool should normally instead
+ * use the within-computation forms listed in the table unless using
+ * async event-style tasks that are not usually joined, in which case
+ * there is little difference among choice of methods.
*
* <table BORDER CELLPADDING=3 CELLSPACING=1>
* <tr>
@@ -96,22 +97,16 @@
* </tr>
* </table>
*
- * <p><b>Sample Usage.</b> Normally a single {@code ForkJoinPool} is
- * used for all parallel task execution in a program or subsystem.
- * Otherwise, use would not usually outweigh the construction and
- * bookkeeping overhead of creating a large set of threads. For
- * example, a common pool could be used for the {@code SortTasks}
- * illustrated in {@link RecursiveAction}. Because {@code
- * ForkJoinPool} uses threads in {@linkplain java.lang.Thread#isDaemon
- * daemon} mode, there is typically no need to explicitly {@link
- * #shutdown} such a pool upon program exit.
- *
- * <pre> {@code
- * static final ForkJoinPool mainPool = new ForkJoinPool();
- * ...
- * public void sort(long[] array) {
- * mainPool.invoke(new SortTask(array, 0, array.length));
- * }}</pre>
+ * <p>The common pool is by default constructed with default
+ * parameters, but these may be controlled by setting three {@link
+ * System#getProperty system properties} with prefix {@code
+ * java.util.concurrent.ForkJoinPool.common}: {@code parallelism} --
+ * an integer greater than zero, {@code threadFactory} -- the class
+ * name of a {@link ForkJoinWorkerThreadFactory}, and {@code
+ * exceptionHandler} -- the class name of a {@link
+ * java.lang.Thread.UncaughtExceptionHandler
+ * Thread.UncaughtExceptionHandler}. Upon any error in establishing
+ * these settings, default parameters are used.
*
* <p><b>Implementation notes</b>: This implementation restricts the
* maximum number of running threads to 32767. Attempts to create
@@ -131,214 +126,388 @@
/*
* Implementation Overview
*
- * This class provides the central bookkeeping and control for a
- * set of worker threads: Submissions from non-FJ threads enter
- * into a submission queue. Workers take these tasks and typically
- * split them into subtasks that may be stolen by other workers.
- * Preference rules give first priority to processing tasks from
- * their own queues (LIFO or FIFO, depending on mode), then to
- * randomized FIFO steals of tasks in other worker queues, and
- * lastly to new submissions.
+ * This class and its nested classes provide the main
+ * functionality and control for a set of worker threads:
+ * Submissions from non-FJ threads enter into submission queues.
+ * Workers take these tasks and typically split them into subtasks
+ * that may be stolen by other workers. Preference rules give
+ * first priority to processing tasks from their own queues (LIFO
+ * or FIFO, depending on mode), then to randomized FIFO steals of
+ * tasks in other queues.
+ *
+ * WorkQueues
+ * ==========
+ *
+ * Most operations occur within work-stealing queues (in nested
+ * class WorkQueue). These are special forms of Deques that
+ * support only three of the four possible end-operations -- push,
+ * pop, and poll (aka steal), under the further constraints that
+ * push and pop are called only from the owning thread (or, as
+ * extended here, under a lock), while poll may be called from
+ * other threads. (If you are unfamiliar with them, you probably
+ * want to read Herlihy and Shavit's book "The Art of
+ * Multiprocessor programming", chapter 16 describing these in
+ * more detail before proceeding.) The main work-stealing queue
+ * design is roughly similar to those in the papers "Dynamic
+ * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
+ * (http://research.sun.com/scalable/pubs/index.html) and
+ * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
+ * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
+ * The main differences ultimately stem from GC requirements that
+ * we null out taken slots as soon as we can, to maintain as small
+ * a footprint as possible even in programs generating huge
+ * numbers of tasks. To accomplish this, we shift the CAS
+ * arbitrating pop vs poll (steal) from being on the indices
+ * ("base" and "top") to the slots themselves. So, both a
+ * successful pop and poll mainly entail a CAS of a slot from
+ * non-null to null. Because we rely on CASes of references, we
+ * do not need tag bits on base or top. They are simple ints as
+ * used in any circular array-based queue (see for example
+ * ArrayDeque). Updates to the indices must still be ordered in a
+ * way that guarantees that top == base means the queue is empty,
+ * but otherwise may err on the side of possibly making the queue
+ * appear nonempty when a push, pop, or poll have not fully
+ * committed. Note that this means that the poll operation,
+ * considered individually, is not wait-free. One thief cannot
+ * successfully continue until another in-progress one (or, if
+ * previously empty, a push) completes. However, in the
+ * aggregate, we ensure at least probabilistic non-blockingness.
+ * If an attempted steal fails, a thief always chooses a different
+ * random victim target to try next. So, in order for one thief to
+ * progress, it suffices for any in-progress poll or new push on
+ * any empty queue to complete. (This is why we normally use
+ * method pollAt and its variants that try once at the apparent
+ * base index, else consider alternative actions, rather than
+ * method poll.)
+ *
+ * This approach also enables support of a user mode in which local
+ * task processing is in FIFO, not LIFO order, simply by using
+ * poll rather than pop. This can be useful in message-passing
+ * frameworks in which tasks are never joined. However neither
+ * mode considers affinities, loads, cache localities, etc, so
+ * rarely provide the best possible performance on a given
+ * machine, but portably provide good throughput by averaging over
+ * these factors. (Further, even if we did try to use such
+ * information, we do not usually have a basis for exploiting it.
+ * For example, some sets of tasks profit from cache affinities,
+ * but others are harmed by cache pollution effects.)
+ *
+ * WorkQueues are also used in a similar way for tasks submitted
+ * to the pool. We cannot mix these tasks in the same queues used
+ * for work-stealing (this would contaminate lifo/fifo
+ * processing). Instead, we randomly associate submission queues
+ * with submitting threads, using a form of hashing. The
+ * ThreadLocal Submitter class contains a value initially used as
+ * a hash code for choosing existing queues, but may be randomly
+ * repositioned upon contention with other submitters. In
+ * essence, submitters act like workers except that they are
+ * restricted to executing local tasks that they submitted (or in
+ * the case of CountedCompleters, others with the same root task).
+ * However, because most shared/external queue operations are more
+ * expensive than internal, and because, at steady state, external
+ * submitters will compete for CPU with workers, ForkJoinTask.join
+ * and related methods disable them from repeatedly helping to
+ * process tasks if all workers are active. Insertion of tasks in
+ * shared mode requires a lock (mainly to protect in the case of
+ * resizing) but we use only a simple spinlock (using bits in
+ * field qlock), because submitters encountering a busy queue move
+ * on to try or create other queues -- they block only when
+ * creating and registering new queues.
+ *
+ * Management
+ * ==========
*
* The main throughput advantages of work-stealing stem from
* decentralized control -- workers mostly take tasks from
* themselves or each other. We cannot negate this in the
* implementation of other management responsibilities. The main
* tactic for avoiding bottlenecks is packing nearly all
- * essentially atomic control state into a single 64bit volatile
- * variable ("ctl"). This variable is read on the order of 10-100
- * times as often as it is modified (always via CAS). (There is
- * some additional control state, for example variable "shutdown"
- * for which we can cope with uncoordinated updates.) This
- * streamlines synchronization and control at the expense of messy
- * constructions needed to repack status bits upon updates.
- * Updates tend not to contend with each other except during
- * bursts while submitted tasks begin or end. In some cases when
- * they do contend, threads can instead do something else
- * (usually, scan for tasks) until contention subsides.
+ * essentially atomic control state into two volatile variables
+ * that are by far most often read (not written) as status and
+ * consistency checks.
*
- * To enable packing, we restrict maximum parallelism to (1<<15)-1
- * (which is far in excess of normal operating range) to allow
- * ids, counts, and their negations (used for thresholding) to fit
- * into 16bit fields.
+ * Field "ctl" contains 64 bits holding all the information needed
+ * to atomically decide to add, inactivate, enqueue (on an event
+ * queue), dequeue, and/or re-activate workers. To enable this
+ * packing, we restrict maximum parallelism to (1<<15)-1 (which is
+ * far in excess of normal operating range) to allow ids, counts,
+ * and their negations (used for thresholding) to fit into 16bit
+ * fields.
*
- * Recording Workers. Workers are recorded in the "workers" array
- * that is created upon pool construction and expanded if (rarely)
- * necessary. This is an array as opposed to some other data
- * structure to support index-based random steals by workers.
- * Updates to the array recording new workers and unrecording
- * terminated ones are protected from each other by a seqLock
- * (scanGuard) but the array is otherwise concurrently readable,
- * and accessed directly by workers. To simplify index-based
- * operations, the array size is always a power of two, and all
- * readers must tolerate null slots. To avoid flailing during
- * start-up, the array is presized to hold twice #parallelism
- * workers (which is unlikely to need further resizing during
- * execution). But to avoid dealing with so many null slots,
- * variable scanGuard includes a mask for the nearest power of two
- * that contains all current workers. All worker thread creation
- * is on-demand, triggered by task submissions, replacement of
- * terminated workers, and/or compensation for blocked
- * workers. However, all other support code is set up to work with
- * other policies. To ensure that we do not hold on to worker
- * references that would prevent GC, ALL accesses to workers are
- * via indices into the workers array (which is one source of some
- * of the messy code constructions here). In essence, the workers
- * array serves as a weak reference mechanism. Thus for example
- * the wait queue field of ctl stores worker indices, not worker
- * references. Access to the workers in associated methods (for
- * example signalWork) must both index-check and null-check the
- * IDs. All such accesses ignore bad IDs by returning out early
- * from what they are doing, since this can only be associated
- * with termination, in which case it is OK to give up.
+ * Field "plock" is a form of sequence lock with a saturating
+ * shutdown bit (similarly for per-queue "qlocks"), mainly
+ * protecting updates to the workQueues array, as well as to
+ * enable shutdown. When used as a lock, it is normally only very
+ * briefly held, so is nearly always available after at most a
+ * brief spin, but we use a monitor-based backup strategy to
+ * block when needed.
*
- * All uses of the workers array, as well as queue arrays, check
- * that the array is non-null (even if previously non-null). This
- * allows nulling during termination, which is currently not
- * necessary, but remains an option for resource-revocation-based
- * shutdown schemes.
+ * Recording WorkQueues. WorkQueues are recorded in the
+ * "workQueues" array that is created upon first use and expanded
+ * if necessary. Updates to the array while recording new workers
+ * and unrecording terminated ones are protected from each other
+ * by a lock but the array is otherwise concurrently readable, and
+ * accessed directly. To simplify index-based operations, the
+ * array size is always a power of two, and all readers must
+ * tolerate null slots. Worker queues are at odd indices. Shared
+ * (submission) queues are at even indices, up to a maximum of 64
+ * slots, to limit growth even if array needs to expand to add
+ * more workers. Grouping them together in this way simplifies and
+ * speeds up task scanning.
*
- * Wait Queuing. Unlike HPC work-stealing frameworks, we cannot
+ * All worker thread creation is on-demand, triggered by task
+ * submissions, replacement of terminated workers, and/or
+ * compensation for blocked workers. However, all other support
+ * code is set up to work with other policies. To ensure that we
+ * do not hold on to worker references that would prevent GC, ALL
+ * accesses to workQueues are via indices into the workQueues
+ * array (which is one source of some of the messy code
+ * constructions here). In essence, the workQueues array serves as
+ * a weak reference mechanism. Thus for example the wait queue
+ * field of ctl stores indices, not references. Access to the
+ * workQueues in associated methods (for example signalWork) must
+ * both index-check and null-check the IDs. All such accesses
+ * ignore bad IDs by returning out early from what they are doing,
+ * since this can only be associated with termination, in which
+ * case it is OK to give up. All uses of the workQueues array
+ * also check that it is non-null (even if previously
+ * non-null). This allows nulling during termination, which is
+ * currently not necessary, but remains an option for
+ * resource-revocation-based shutdown schemes. It also helps
+ * reduce JIT issuance of uncommon-trap code, which tends to
+ * unnecessarily complicate control flow in some methods.
+ *
+ * Event Queuing. Unlike HPC work-stealing frameworks, we cannot
* let workers spin indefinitely scanning for tasks when none can
* be found immediately, and we cannot start/resume workers unless
* there appear to be tasks available. On the other hand, we must
* quickly prod them into action when new tasks are submitted or
- * generated. We park/unpark workers after placing in an event
- * wait queue when they cannot find work. This "queue" is actually
- * a simple Treiber stack, headed by the "id" field of ctl, plus a
- * 15bit counter value to both wake up waiters (by advancing their
- * count) and avoid ABA effects. Successors are held in worker
- * field "nextWait". Queuing deals with several intrinsic races,
- * mainly that a task-producing thread can miss seeing (and
+ * generated. In many usages, ramp-up time to activate workers is
+ * the main limiting factor in overall performance (this is
+ * compounded at program start-up by JIT compilation and
+ * allocation). So we try to streamline this as much as possible.
+ * We park/unpark workers after placing in an event wait queue
+ * when they cannot find work. This "queue" is actually a simple
+ * Treiber stack, headed by the "id" field of ctl, plus a 15bit
+ * counter value (that reflects the number of times a worker has
+ * been inactivated) to avoid ABA effects (we need only as many
+ * version numbers as worker threads). Successors are held in
+ * field WorkQueue.nextWait. Queuing deals with several intrinsic
+ * races, mainly that a task-producing thread can miss seeing (and
* signalling) another thread that gave up looking for work but
* has not yet entered the wait queue. We solve this by requiring
- * a full sweep of all workers both before (in scan()) and after
- * (in tryAwaitWork()) a newly waiting worker is added to the wait
- * queue. During a rescan, the worker might release some other
- * queued worker rather than itself, which has the same net
- * effect. Because enqueued workers may actually be rescanning
- * rather than waiting, we set and clear the "parked" field of
- * ForkJoinWorkerThread to reduce unnecessary calls to unpark.
- * (Use of the parked field requires a secondary recheck to avoid
- * missed signals.)
+ * a full sweep of all workers (via repeated calls to method
+ * scan()) both before and after a newly waiting worker is added
+ * to the wait queue. During a rescan, the worker might release
+ * some other queued worker rather than itself, which has the same
+ * net effect. Because enqueued workers may actually be rescanning
+ * rather than waiting, we set and clear the "parker" field of
+ * WorkQueues to reduce unnecessary calls to unpark. (This
+ * requires a secondary recheck to avoid missed signals.) Note
+ * the unusual conventions about Thread.interrupts surrounding
+ * parking and other blocking: Because interrupts are used solely
+ * to alert threads to check termination, which is checked anyway
+ * upon blocking, we clear status (using Thread.interrupted)
+ * before any call to park, so that park does not immediately
+ * return due to status being set via some other unrelated call to
+ * interrupt in user code.
*
* Signalling. We create or wake up workers only when there
* appears to be at least one task they might be able to find and
- * execute. When a submission is added or another worker adds a
- * task to a queue that previously had two or fewer tasks, they
- * signal waiting workers (or trigger creation of new ones if
- * fewer than the given parallelism level -- see signalWork).
- * These primary signals are buttressed by signals during rescans
- * as well as those performed when a worker steals a task and
- * notices that there are more tasks too; together these cover the
- * signals needed in cases when more than two tasks are pushed
- * but untaken.
+ * execute. However, many other threads may notice the same task
+ * and each signal to wake up a thread that might take it. So in
+ * general, pools will be over-signalled. When a submission is
+ * added or another worker adds a task to a queue that has fewer
+ * than two tasks, they signal waiting workers (or trigger
+ * creation of new ones if fewer than the given parallelism level
+ * -- signalWork), and may leave a hint to the unparked worker to
+ * help signal others upon wakeup). These primary signals are
+ * buttressed by others (see method helpSignal) whenever other
+ * threads scan for work or do not have a task to process. On
+ * most platforms, signalling (unpark) overhead time is noticeably
+ * long, and the time between signalling a thread and it actually
+ * making progress can be very noticeably long, so it is worth
+ * offloading these delays from critical paths as much as
+ * possible.
*
* Trimming workers. To release resources after periods of lack of
* use, a worker starting to wait when the pool is quiescent will
- * time out and terminate if the pool has remained quiescent for
- * SHRINK_RATE nanosecs. This will slowly propagate, eventually
- * terminating all workers after long periods of non-use.
+ * time out and terminate if the pool has remained quiescent for a
+ * given period -- a short period if there are more threads than
+ * parallelism, longer as the number of threads decreases. This
+ * will slowly propagate, eventually terminating all workers after
+ * periods of non-use.
*
- * Submissions. External submissions are maintained in an
- * array-based queue that is structured identically to
- * ForkJoinWorkerThread queues except for the use of
- * submissionLock in method addSubmission. Unlike the case for
- * worker queues, multiple external threads can add new
- * submissions, so adding requires a lock.
+ * Shutdown and Termination. A call to shutdownNow atomically sets
+ * a plock bit and then (non-atomically) sets each worker's
+ * qlock status, cancels all unprocessed tasks, and wakes up
+ * all waiting workers. Detecting whether termination should
+ * commence after a non-abrupt shutdown() call requires more work
+ * and bookkeeping. We need consensus about quiescence (i.e., that
+ * there is no more work). The active count provides a primary
+ * indication but non-abrupt shutdown still requires a rechecking
+ * scan for any workers that are inactive but not queued.
*
- * Compensation. Beyond work-stealing support and lifecycle
- * control, the main responsibility of this framework is to take
- * actions when one worker is waiting to join a task stolen (or
- * always held by) another. Because we are multiplexing many
- * tasks on to a pool of workers, we can't just let them block (as
- * in Thread.join). We also cannot just reassign the joiner's
- * run-time stack with another and replace it later, which would
- * be a form of "continuation", that even if possible is not
- * necessarily a good idea since we sometimes need both an
- * unblocked task and its continuation to progress. Instead we
- * combine two tactics:
+ * Joining Tasks
+ * =============
+ *
+ * Any of several actions may be taken when one worker is waiting
+ * to join a task stolen (or always held) by another. Because we
+ * are multiplexing many tasks on to a pool of workers, we can't
+ * just let them block (as in Thread.join). We also cannot just
+ * reassign the joiner's run-time stack with another and replace
+ * it later, which would be a form of "continuation", that even if
+ * possible is not necessarily a good idea since we sometimes need
+ * both an unblocked task and its continuation to progress.
+ * Instead we combine two tactics:
*
* Helping: Arranging for the joiner to execute some task that it
- * would be running if the steal had not occurred. Method
- * ForkJoinWorkerThread.joinTask tracks joining->stealing
- * links to try to find such a task.
+ * would be running if the steal had not occurred.
*
* Compensating: Unless there are already enough live threads,
- * method tryPreBlock() may create or re-activate a spare
- * thread to compensate for blocked joiners until they
- * unblock.
+ * method tryCompensate() may create or re-activate a spare
+ * thread to compensate for blocked joiners until they unblock.
+ *
+ * A third form (implemented in tryRemoveAndExec) amounts to
+ * helping a hypothetical compensator: If we can readily tell that
+ * a possible action of a compensator is to steal and execute the
+ * task being joined, the joining thread can do so directly,
+ * without the need for a compensation thread (although at the
+ * expense of larger run-time stacks, but the tradeoff is
+ * typically worthwhile).
*
* The ManagedBlocker extension API can't use helping so relies
* only on compensation in method awaitBlocker.
*
+ * The algorithm in tryHelpStealer entails a form of "linear"
+ * helping: Each worker records (in field currentSteal) the most
+ * recent task it stole from some other worker. Plus, it records
+ * (in field currentJoin) the task it is currently actively
+ * joining. Method tryHelpStealer uses these markers to try to
+ * find a worker to help (i.e., steal back a task from and execute
+ * it) that could hasten completion of the actively joined task.
+ * In essence, the joiner executes a task that would be on its own
+ * local deque had the to-be-joined task not been stolen. This may
+ * be seen as a conservative variant of the approach in Wagner &
+ * Calder "Leapfrogging: a portable technique for implementing
+ * efficient futures" SIGPLAN Notices, 1993
+ * (http://portal.acm.org/citation.cfm?id=155354). It differs in
+ * that: (1) We only maintain dependency links across workers upon
+ * steals, rather than use per-task bookkeeping. This sometimes
+ * requires a linear scan of workQueues array to locate stealers,
+ * but often doesn't because stealers leave hints (that may become
+ * stale/wrong) of where to locate them. It is only a hint
+ * because a worker might have had multiple steals and the hint
+ * records only one of them (usually the most current). Hinting
+ * isolates cost to when it is needed, rather than adding to
+ * per-task overhead. (2) It is "shallow", ignoring nesting and
+ * potentially cyclic mutual steals. (3) It is intentionally
+ * racy: field currentJoin is updated only while actively joining,
+ * which means that we miss links in the chain during long-lived
+ * tasks, GC stalls etc (which is OK since blocking in such cases
+ * is usually a good idea). (4) We bound the number of attempts
+ * to find work (see MAX_HELP) and fall back to suspending the
+ * worker and if necessary replacing it with another.
+ *
+ * Helping actions for CountedCompleters are much simpler: Method
+ * helpComplete can take and execute any task with the same root
+ * as the task being waited on. However, this still entails some
+ * traversal of completer chains, so is less efficient than using
+ * CountedCompleters without explicit joins.
+ *
* It is impossible to keep exactly the target parallelism number
* of threads running at any given time. Determining the
* existence of conservatively safe helping targets, the
* availability of already-created spares, and the apparent need
- * to create new spares are all racy and require heuristic
- * guidance, so we rely on multiple retries of each. Currently,
- * in keeping with on-demand signalling policy, we compensate only
- * if blocking would leave less than one active (non-waiting,
- * non-blocked) worker. Additionally, to avoid some false alarms
- * due to GC, lagging counters, system activity, etc, compensated
- * blocking for joins is only attempted after rechecks stabilize
- * (retries are interspersed with Thread.yield, for good
- * citizenship). The variable blockedCount, incremented before
- * blocking and decremented after, is sometimes needed to
- * distinguish cases of waiting for work vs blocking on joins or
- * other managed sync. Both cases are equivalent for most pool
- * control, so we can update non-atomically. (Additionally,
- * contention on blockedCount alleviates some contention on ctl).
+ * to create new spares are all racy, so we rely on multiple
+ * retries of each. Compensation in the apparent absence of
+ * helping opportunities is challenging to control on JVMs, where
+ * GC and other activities can stall progress of tasks that in
+ * turn stall out many other dependent tasks, without us being
+ * able to determine whether they will ever require compensation.
+ * Even though work-stealing otherwise encounters little
+ * degradation in the presence of more threads than cores,
+ * aggressively adding new threads in such cases entails risk of
+ * unwanted positive feedback control loops in which more threads
+ * cause more dependent stalls (as well as delayed progress of
+ * unblocked threads to the point that we know they are available)
+ * leading to more situations requiring more threads, and so
+ * on. This aspect of control can be seen as an (analytically
+ * intractable) game with an opponent that may choose the worst
+ * (for us) active thread to stall at any time. We take several
+ * precautions to bound losses (and thus bound gains), mainly in
+ * methods tryCompensate and awaitJoin.
*
- * Shutdown and Termination. A call to shutdownNow atomically sets
- * the ctl stop bit and then (non-atomically) sets each workers
- * "terminate" status, cancels all unprocessed tasks, and wakes up
- * all waiting workers. Detecting whether termination should
- * commence after a non-abrupt shutdown() call requires more work
- * and bookkeeping. We need consensus about quiescence (i.e., that
- * there is no more work) which is reflected in active counts so
- * long as there are no current blockers, as well as possible
- * re-evaluations during independent changes in blocking or
- * quiescing workers.
+ * Common Pool
+ * ===========
*
- * Style notes: There is a lot of representation-level coupling
- * among classes ForkJoinPool, ForkJoinWorkerThread, and
- * ForkJoinTask. Most fields of ForkJoinWorkerThread maintain
- * data structures managed by ForkJoinPool, so are directly
- * accessed. Conversely we allow access to "workers" array by
- * workers, and direct access to ForkJoinTask.status by both
- * ForkJoinPool and ForkJoinWorkerThread. There is little point
+ * The static commonPool always exists after static
+ * initialization. Since it (or any other created pool) need
+ * never be used, we minimize initial construction overhead and
+ * footprint to the setup of about a dozen fields, with no nested
+ * allocation. Most bootstrapping occurs within method
+ * fullExternalPush during the first submission to the pool.
+ *
+ * When external threads submit to the common pool, they can
+ * perform some subtask processing (see externalHelpJoin and
+ * related methods). We do not need to record whether these
+ * submissions are to the common pool -- if not, externalHelpJoin
+ * returns quickly (at the most helping to signal some common pool
+ * workers). These submitters would otherwise be blocked waiting
+ * for completion, so the extra effort (with liberally sprinkled
+ * task status checks) in inapplicable cases amounts to an odd
+ * form of limited spin-wait before blocking in ForkJoinTask.join.
+ *
+ * Style notes
+ * ===========
+ *
+ * There is a lot of representation-level coupling among classes
+ * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The
+ * fields of WorkQueue maintain data structures managed by
+ * ForkJoinPool, so are directly accessed. There is little point
* trying to reduce this, since any associated future changes in
* representations will need to be accompanied by algorithmic
- * changes anyway. All together, these low-level implementation
- * choices produce as much as a factor of 4 performance
- * improvement compared to naive implementations, and enable the
- * processing of billions of tasks per second, at the expense of
- * some ugliness.
+ * changes anyway. Several methods intrinsically sprawl because
+ * they must accumulate sets of consistent reads of volatiles held
+ * in local variables. Methods signalWork() and scan() are the
+ * main bottlenecks, so are especially heavily
+ * micro-optimized/mangled. There are lots of inline assignments
+ * (of form "while ((local = field) != 0)") which are usually the
+ * simplest way to ensure the required read orderings (which are
+ * sometimes critical). This leads to a "C"-like style of listing
+ * declarations of these locals at the heads of methods or blocks.
+ * There are several occurrences of the unusual "do {} while
+ * (!cas...)" which is the simplest way to force an update of a
+ * CAS'ed variable. There are also other coding oddities (including
+ * several unnecessary-looking hoisted null checks) that help
+ * some methods perform reasonably even when interpreted (not
+ * compiled).
*
- * Methods signalWork() and scan() are the main bottlenecks so are
- * especially heavily micro-optimized/mangled. There are lots of
- * inline assignments (of form "while ((local = field) != 0)")
- * which are usually the simplest way to ensure the required read
- * orderings (which are sometimes critical). This leads to a
- * "C"-like style of listing declarations of these locals at the
- * heads of methods or blocks. There are several occurrences of
- * the unusual "do {} while (!cas...)" which is the simplest way
- * to force an update of a CAS'ed variable. There are also other
- * coding oddities that help some methods perform reasonably even
- * when interpreted (not compiled).
- *
- * The order of declarations in this file is: (1) declarations of
- * statics (2) fields (along with constants used when unpacking
- * some of them), listed in an order that tends to reduce
- * contention among them a bit under most JVMs. (3) internal
- * control methods (4) callbacks and other support for
- * ForkJoinTask and ForkJoinWorkerThread classes, (5) exported
- * methods (plus a few little helpers). (6) static block
- * initializing all statics in a minimally dependent order.
+ * The order of declarations in this file is:
+ * (1) Static utility functions
+ * (2) Nested (static) classes
+ * (3) Static fields
+ * (4) Fields, along with constants used when unpacking some of them
+ * (5) Internal control methods
+ * (6) Callbacks and other support for ForkJoinTask methods
+ * (7) Exported methods
+ * (8) Static block initializing statics in minimally dependent order
*/
+ // Static utilities
+
+ /**
+ * If there is a security manager, makes sure caller has
+ * permission to modify threads.
+ */
+ private static void checkPermission() {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null)
+ security.checkPermission(modifyThreadPermission);
+ }
+
+ // Nested classes
+
/**
* Factory for creating new {@link ForkJoinWorkerThread}s.
* A {@code ForkJoinWorkerThreadFactory} must be defined and used
@@ -359,14 +528,525 @@
* Default ForkJoinWorkerThreadFactory implementation; creates a
* new ForkJoinWorkerThread.
*/
- static class DefaultForkJoinWorkerThreadFactory
+ static final class DefaultForkJoinWorkerThreadFactory
implements ForkJoinWorkerThreadFactory {
- public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+ public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
return new ForkJoinWorkerThread(pool);
}
}
/**
+ * Per-thread records for threads that submit to pools. Currently
+ * holds only pseudo-random seed / index that is used to choose
+ * submission queues in method externalPush. In the future, this may
+ * also incorporate a means to implement different task rejection
+ * and resubmission policies.
+ *
+ * Seeds for submitters and workers/workQueues work in basically
+ * the same way but are initialized and updated using slightly
+ * different mechanics. Both are initialized using the same
+ * approach as in class ThreadLocal, where successive values are
+ * unlikely to collide with previous values. Seeds are then
+ * randomly modified upon collisions using xorshifts, which
+ * requires a non-zero seed.
+ */
+ static final class Submitter {
+ int seed;
+ Submitter(int s) { seed = s; }
+ }
+
+ /**
+ * Class for artificial tasks that are used to replace the target
+ * of local joins if they are removed from an interior queue slot
+ * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
+ * actually do anything beyond having a unique identity.
+ */
+ static final class EmptyTask extends ForkJoinTask<Void> {
+ private static final long serialVersionUID = -7721805057305804111L;
+ EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
+ public final Void getRawResult() { return null; }
+ public final void setRawResult(Void x) {}
+ public final boolean exec() { return true; }
+ }
+
+ /**
+ * Queues supporting work-stealing as well as external task
+ * submission. See above for main rationale and algorithms.
+ * Implementation relies heavily on "Unsafe" intrinsics
+ * and selective use of "volatile":
+ *
+ * Field "base" is the index (mod array.length) of the least valid
+ * queue slot, which is always the next position to steal (poll)
+ * from if nonempty. Reads and writes require volatile orderings
+ * but not CAS, because updates are only performed after slot
+ * CASes.
+ *
+ * Field "top" is the index (mod array.length) of the next queue
+ * slot to push to or pop from. It is written only by owner thread
+ * for push, or under lock for external/shared push, and accessed
+ * by other threads only after reading (volatile) base. Both top
+ * and base are allowed to wrap around on overflow, but (top -
+ * base) (or more commonly -(base - top) to force volatile read of
+ * base before top) still estimates size. The lock ("qlock") is
+ * forced to -1 on termination, causing all further lock attempts
+ * to fail. (Note: we don't need CAS for termination state because
+ * upon pool shutdown, all shared-queues will stop being used
+ * anyway.) Nearly all lock bodies are set up so that exceptions
+ * within lock bodies are "impossible" (modulo JVM errors that
+ * would cause failure anyway.)
+ *
+ * The array slots are read and written using the emulation of
+ * volatiles/atomics provided by Unsafe. Insertions must in
+ * general use putOrderedObject as a form of releasing store to
+ * ensure that all writes to the task object are ordered before
+ * its publication in the queue. All removals entail a CAS to
+ * null. The array is always a power of two. To ensure safety of
+ * Unsafe array operations, all accesses perform explicit null
+ * checks and implicit bounds checks via power-of-two masking.
+ *
+ * In addition to basic queuing support, this class contains
+ * fields described elsewhere to control execution. It turns out
+ * to work better memory-layout-wise to include them in this class
+ * rather than a separate class.
+ *
+ * Performance on most platforms is very sensitive to placement of
+ * instances of both WorkQueues and their arrays -- we absolutely
+ * do not want multiple WorkQueue instances or multiple queue
+ * arrays sharing cache lines. (It would be best for queue objects
+ * and their arrays to share, but there is nothing available to
+ * help arrange that). Unfortunately, because they are recorded
+ * in a common array, WorkQueue instances are often moved to be
+ * adjacent by garbage collectors. To reduce impact, we use field
+ * padding that works OK on common platforms; this effectively
+ * trades off slightly slower average field access for the sake of
+ * avoiding really bad worst-case access. (Until better JVM
+ * support is in place, this padding is dependent on transient
+ * properties of JVM field layout rules.) We also take care in
+ * allocating, sizing and resizing the array. Non-shared queue
+ * arrays are initialized by workers before use. Others are
+ * allocated on first use.
+ */
+ static final class WorkQueue {
+ /**
+ * Capacity of work-stealing queue array upon initialization.
+ * Must be a power of two; at least 4, but should be larger to
+ * reduce or eliminate cacheline sharing among queues.
+ * Currently, it is much larger, as a partial workaround for
+ * the fact that JVMs often place arrays in locations that
+ * share GC bookkeeping (especially cardmarks) such that
+ * per-write accesses encounter serious memory contention.
+ */
+ static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
+
+ /**
+ * Maximum size for queue arrays. Must be a power of two less
+ * than or equal to 1 << (31 - width of array entry) to ensure
+ * lack of wraparound of index calculations, but defined to a
+ * value a bit less than this to help users trap runaway
+ * programs before saturating systems.
+ */
+ static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
+
+ // Heuristic padding to ameliorate unfortunate memory placements
+ volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
+
+ int seed; // for random scanning; initialize nonzero
+ volatile int eventCount; // encoded inactivation count; < 0 if inactive
+ int nextWait; // encoded record of next event waiter
+ int hint; // steal or signal hint (index)
+ int poolIndex; // index of this queue in pool (or 0)
+ final int mode; // 0: lifo, > 0: fifo, < 0: shared
+ int nsteals; // number of steals
+ volatile int qlock; // 1: locked, -1: terminate; else 0
+ volatile int base; // index of next slot for poll
+ int top; // index of next slot for push
+ ForkJoinTask<?>[] array; // the elements (initially unallocated)
+ final ForkJoinPool pool; // the containing pool (may be null)
+ final ForkJoinWorkerThread owner; // owning thread or null if shared
+ volatile Thread parker; // == owner during call to park; else null
+ volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
+ ForkJoinTask<?> currentSteal; // current non-local task being executed
+
+ volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+ volatile Object pad18, pad19, pad1a, pad1b, pad1c, pad1d;
+
+ WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode,
+ int seed) {
+ this.pool = pool;
+ this.owner = owner;
+ this.mode = mode;
+ this.seed = seed;
+ // Place indices in the center of array (that is not yet allocated)
+ base = top = INITIAL_QUEUE_CAPACITY >>> 1;
+ }
+
+ /**
+ * Returns the approximate number of tasks in the queue.
+ */
+ final int queueSize() {
+ int n = base - top; // non-owner callers must read base first
+ return (n >= 0) ? 0 : -n; // ignore transient negative
+ }
+
+ /**
+ * Provides a more accurate estimate of whether this queue has
+ * any tasks than does queueSize, by checking whether a
+ * near-empty queue has at least one unclaimed task.
+ */
+ final boolean isEmpty() {
+ ForkJoinTask<?>[] a; int m, s;
+ int n = base - (s = top);
+ return (n >= 0 ||
+ (n == -1 &&
+ ((a = array) == null ||
+ (m = a.length - 1) < 0 ||
+ U.getObject
+ (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null)));
+ }
+
+ /**
+ * Pushes a task. Call only by owner in unshared queues. (The
+ * shared-queue version is embedded in method externalPush.)
+ *
+ * @param task the task. Caller must ensure non-null.
+ * @throws RejectedExecutionException if array cannot be resized
+ */
+ final void push(ForkJoinTask<?> task) {
+ ForkJoinTask<?>[] a; ForkJoinPool p;
+ int s = top, m, n;
+ if ((a = array) != null) { // ignore if queue removed
+ int j = (((m = a.length - 1) & s) << ASHIFT) + ABASE;
+ U.putOrderedObject(a, j, task);
+ if ((n = (top = s + 1) - base) <= 2) {
+ if ((p = pool) != null)
+ p.signalWork(this);
+ }
+ else if (n >= m)
+ growArray();
+ }
+ }
+
+ /**
+ * Initializes or doubles the capacity of array. Call either
+ * by owner or with lock held -- it is OK for base, but not
+ * top, to move while resizings are in progress.
+ */
+ final ForkJoinTask<?>[] growArray() {
+ ForkJoinTask<?>[] oldA = array;
+ int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
+ if (size > MAXIMUM_QUEUE_CAPACITY)
+ throw new RejectedExecutionException("Queue capacity exceeded");
+ int oldMask, t, b;
+ ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
+ if (oldA != null && (oldMask = oldA.length - 1) >= 0 &&
+ (t = top) - (b = base) > 0) {
+ int mask = size - 1;
+ do {
+ ForkJoinTask<?> x;
+ int oldj = ((b & oldMask) << ASHIFT) + ABASE;
+ int j = ((b & mask) << ASHIFT) + ABASE;
+ x = (ForkJoinTask<?>)U.getObjectVolatile(oldA, oldj);
+ if (x != null &&
+ U.compareAndSwapObject(oldA, oldj, x, null))
+ U.putObjectVolatile(a, j, x);
+ } while (++b != t);
+ }
+ return a;
+ }
+
+ /**
+ * Takes next task, if one exists, in LIFO order. Call only
+ * by owner in unshared queues.
+ */
+ final ForkJoinTask<?> pop() {
+ ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
+ if ((a = array) != null && (m = a.length - 1) >= 0) {
+ for (int s; (s = top - 1) - base >= 0;) {
+ long j = ((m & s) << ASHIFT) + ABASE;
+ if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
+ break;
+ if (U.compareAndSwapObject(a, j, t, null)) {
+ top = s;
+ return t;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Takes a task in FIFO order if b is base of queue and a task
+ * can be claimed without contention. Specialized versions
+ * appear in ForkJoinPool methods scan and tryHelpStealer.
+ */
+ final ForkJoinTask<?> pollAt(int b) {
+ ForkJoinTask<?> t; ForkJoinTask<?>[] a;
+ if ((a = array) != null) {
+ int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) != null &&
+ base == b &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ base = b + 1;
+ return t;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Takes next task, if one exists, in FIFO order.
+ */
+ final ForkJoinTask<?> poll() {
+ ForkJoinTask<?>[] a; int b; ForkJoinTask<?> t;
+ while ((b = base) - top < 0 && (a = array) != null) {
+ int j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ if (t != null) {
+ if (base == b &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ base = b + 1;
+ return t;
+ }
+ }
+ else if (base == b) {
+ if (b + 1 == top)
+ break;
+ Thread.yield(); // wait for lagging update (very rare)
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Takes next task, if one exists, in order specified by mode.
+ */
+ final ForkJoinTask<?> nextLocalTask() {
+ return mode == 0 ? pop() : poll();
+ }
+
+ /**
+ * Returns next task, if one exists, in order specified by mode.
+ */
+ final ForkJoinTask<?> peek() {
+ ForkJoinTask<?>[] a = array; int m;
+ if (a == null || (m = a.length - 1) < 0)
+ return null;
+ int i = mode == 0 ? top - 1 : base;
+ int j = ((i & m) << ASHIFT) + ABASE;
+ return (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ }
+
+ /**
+ * Pops the given task only if it is at the current top.
+ * (A shared version is available only via FJP.tryExternalUnpush)
+ */
+ final boolean tryUnpush(ForkJoinTask<?> t) {
+ ForkJoinTask<?>[] a; int s;
+ if ((a = array) != null && (s = top) != base &&
+ U.compareAndSwapObject
+ (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
+ top = s;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Removes and cancels all known tasks, ignoring any exceptions.
+ */
+ final void cancelAll() {
+ ForkJoinTask.cancelIgnoringExceptions(currentJoin);
+ ForkJoinTask.cancelIgnoringExceptions(currentSteal);
+ for (ForkJoinTask<?> t; (t = poll()) != null; )
+ ForkJoinTask.cancelIgnoringExceptions(t);
+ }
+
+ /**
+ * Computes next value for random probes. Scans don't require
+ * a very high quality generator, but also not a crummy one.
+ * Marsaglia xor-shift is cheap and works well enough. Note:
+ * This is manually inlined in its usages in ForkJoinPool to
+ * avoid writes inside busy scan loops.
+ */
+ final int nextSeed() {
+ int r = seed;
+ r ^= r << 13;
+ r ^= r >>> 17;
+ return seed = r ^= r << 5;
+ }
+
+ // Specialized execution methods
+
+ /**
+ * Pops and runs tasks until empty.
+ */
+ private void popAndExecAll() {
+ // A bit faster than repeated pop calls
+ ForkJoinTask<?>[] a; int m, s; long j; ForkJoinTask<?> t;
+ while ((a = array) != null && (m = a.length - 1) >= 0 &&
+ (s = top - 1) - base >= 0 &&
+ (t = ((ForkJoinTask<?>)
+ U.getObject(a, j = ((m & s) << ASHIFT) + ABASE)))
+ != null) {
+ if (U.compareAndSwapObject(a, j, t, null)) {
+ top = s;
+ t.doExec();
+ }
+ }
+ }
+
+ /**
+ * Polls and runs tasks until empty.
+ */
+ private void pollAndExecAll() {
+ for (ForkJoinTask<?> t; (t = poll()) != null;)
+ t.doExec();
+ }
+
+ /**
+ * If present, removes from queue and executes the given task,
+ * or any other cancelled task. Returns (true) on any CAS
+ * or consistency check failure so caller can retry.
+ *
+ * @return false if no progress can be made, else true
+ */
+ final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
+ boolean stat = true, removed = false, empty = true;
+ ForkJoinTask<?>[] a; int m, s, b, n;
+ if ((a = array) != null && (m = a.length - 1) >= 0 &&
+ (n = (s = top) - (b = base)) > 0) {
+ for (ForkJoinTask<?> t;;) { // traverse from s to b
+ int j = ((--s & m) << ASHIFT) + ABASE;
+ t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ if (t == null) // inconsistent length
+ break;
+ else if (t == task) {
+ if (s + 1 == top) { // pop
+ if (!U.compareAndSwapObject(a, j, task, null))
+ break;
+ top = s;
+ removed = true;
+ }
+ else if (base == b) // replace with proxy
+ removed = U.compareAndSwapObject(a, j, task,
+ new EmptyTask());
+ break;
+ }
+ else if (t.status >= 0)
+ empty = false;
+ else if (s + 1 == top) { // pop and throw away
+ if (U.compareAndSwapObject(a, j, t, null))
+ top = s;
+ break;
+ }
+ if (--n == 0) {
+ if (!empty && base == b)
+ stat = false;
+ break;
+ }
+ }
+ }
+ if (removed)
+ task.doExec();
+ return stat;
+ }
+
+ /**
+ * Polls for and executes the given task or any other task in
+ * its CountedCompleter computation.
+ */
+ final boolean pollAndExecCC(ForkJoinTask<?> root) {
+ ForkJoinTask<?>[] a; int b; Object o;
+ outer: while ((b = base) - top < 0 && (a = array) != null) {
+ long j = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ if ((o = U.getObject(a, j)) == null ||
+ !(o instanceof CountedCompleter))
+ break;
+ for (CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;;) {
+ if (r == root) {
+ if (base == b &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ base = b + 1;
+ t.doExec();
+ return true;
+ }
+ else
+ break; // restart
+ }
+ if ((r = r.completer) == null)
+ break outer; // not part of root computation
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Executes a top-level task and any local tasks remaining
+ * after execution.
+ */
+ final void runTask(ForkJoinTask<?> t) {
+ if (t != null) {
+ (currentSteal = t).doExec();
+ currentSteal = null;
+ ++nsteals;
+ if (base - top < 0) { // process remaining local tasks
+ if (mode == 0)
+ popAndExecAll();
+ else
+ pollAndExecAll();
+ }
+ }
+ }
+
+ /**
+ * Executes a non-top-level (stolen) task.
+ */
+ final void runSubtask(ForkJoinTask<?> t) {
+ if (t != null) {
+ ForkJoinTask<?> ps = currentSteal;
+ (currentSteal = t).doExec();
+ currentSteal = ps;
+ }
+ }
+
+ /**
+ * Returns true if owned and not known to be blocked.
+ */
+ final boolean isApparentlyUnblocked() {
+ Thread wt; Thread.State s;
+ return (eventCount >= 0 &&
+ (wt = owner) != null &&
+ (s = wt.getState()) != Thread.State.BLOCKED &&
+ s != Thread.State.WAITING &&
+ s != Thread.State.TIMED_WAITING);
+ }
+
+ // Unsafe mechanics
+ private static final sun.misc.Unsafe U;
+ private static final long QLOCK;
+ private static final int ABASE;
+ private static final int ASHIFT;
+ static {
+ try {
+ U = sun.misc.Unsafe.getUnsafe();
+ Class<?> k = WorkQueue.class;
+ Class<?> ak = ForkJoinTask[].class;
+ QLOCK = U.objectFieldOffset
+ (k.getDeclaredField("qlock"));
+ ABASE = U.arrayBaseOffset(ak);
+ int scale = U.arrayIndexScale(ak);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+ } catch (Exception e) {
+ throw new Error(e);
+ }
+ }
+ }
+
+ // static fields (initialized in static initializer below)
+
+ /**
* Creates a new ForkJoinWorkerThread. This factory is used unless
* overridden in ForkJoinPool constructors.
*/
@@ -374,107 +1054,93 @@
defaultForkJoinWorkerThreadFactory;
/**
+ * Per-thread submission bookkeeping. Shared across all pools
+ * to reduce ThreadLocal pollution and because random motion
+ * to avoid contention in one pool is likely to hold for others.
+ * Lazily initialized on first submission (but null-checked
+ * in other contexts to avoid unnecessary initialization).
+ */
+ static final ThreadLocal<Submitter> submitters;
+
+ /**
* Permission required for callers of methods that may start or
* kill threads.
*/
private static final RuntimePermission modifyThreadPermission;
/**
- * If there is a security manager, makes sure caller has
- * permission to modify threads.
+ * Common (static) pool. Non-null for public use unless a static
+ * construction exception, but internal usages null-check on use
+ * to paranoically avoid potential initialization circularities
+ * as well as to simplify generated code.
*/
- private static void checkPermission() {
- SecurityManager security = System.getSecurityManager();
- if (security != null)
- security.checkPermission(modifyThreadPermission);
+ static final ForkJoinPool commonPool;
+
+ /**
+ * Common pool parallelism. Must equal commonPool.parallelism.
+ */
+ static final int commonPoolParallelism;
+
+ /**
+ * Sequence number for creating workerNamePrefix.
+ */
+ private static int poolNumberSequence;
+
+ /**
+ * Returns the next sequence number. We don't expect this to
+ * ever contend, so use simple builtin sync.
+ */
+ private static final synchronized int nextPoolId() {
+ return ++poolNumberSequence;
}
- /**
- * Generator for assigning sequence numbers as pool names.
- */
- private static final AtomicInteger poolNumberGenerator;
+ // static constants
/**
- * Generator for initial random seeds for worker victim
- * selection. This is used only to create initial seeds. Random
- * steals use a cheaper xorshift generator per steal attempt. We
- * don't expect much contention on seedGenerator, so just use a
- * plain Random.
+ * Initial timeout value (in nanoseconds) for the thread
+ * triggering quiescence to park waiting for new work. On timeout,
+ * the thread will instead try to shrink the number of
+ * workers. The value should be large enough to avoid overly
+ * aggressive shrinkage during most transient stalls (long GCs
+ * etc).
*/
- static final Random workerSeedGenerator;
+ private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec
/**
- * Array holding all worker threads in the pool. Initialized upon
- * construction. Array size must be a power of two. Updates and
- * replacements are protected by scanGuard, but the array is
- * always kept in a consistent enough state to be randomly
- * accessed without locking by workers performing work-stealing,
- * as well as other traversal-based methods in this class, so long
- * as reads memory-acquire by first reading ctl. All readers must
- * tolerate that some array slots may be null.
+ * Timeout value when there are more threads than parallelism level
*/
- ForkJoinWorkerThread[] workers;
+ private static final long FAST_IDLE_TIMEOUT = 200L * 1000L * 1000L;
/**
- * Initial size for submission queue array. Must be a power of
- * two. In many applications, these always stay small so we use a
- * small initial cap.
+ * Tolerance for idle timeouts, to cope with timer undershoots
*/
- private static final int INITIAL_QUEUE_CAPACITY = 8;
+ private static final long TIMEOUT_SLOP = 2000000L; // 20ms
/**
- * Maximum size for submission queue array. Must be a power of two
- * less than or equal to 1 << (31 - width of array entry) to
- * ensure lack of index wraparound, but is capped at a lower
- * value to help users trap runaway computations.
+ * The maximum stolen->joining link depth allowed in method
+ * tryHelpStealer. Must be a power of two. Depths for legitimate
+ * chains are unbounded, but we use a fixed constant to avoid
+ * (otherwise unchecked) cycles and to bound staleness of
+ * traversal parameters at the expense of sometimes blocking when
+ * we could be helping.
*/
- private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
+ private static final int MAX_HELP = 64;
/**
- * Array serving as submission queue. Initialized upon construction.
+ * Increment for seed generators. See class ThreadLocal for
+ * explanation.
*/
- private ForkJoinTask<?>[] submissionQueue;
+ private static final int SEED_INCREMENT = 0x61c88647;
- /**
- * Lock protecting submissions array for addSubmission
- */
- private final ReentrantLock submissionLock;
-
- /**
- * Condition for awaitTermination, using submissionLock for
- * convenience.
- */
- private final Condition termination;
-
- /**
- * Creation factory for worker threads.
- */
- private final ForkJoinWorkerThreadFactory factory;
-
- /**
- * The uncaught exception handler used when any worker abruptly
- * terminates.
- */
- final Thread.UncaughtExceptionHandler ueh;
-
- /**
- * Prefix for assigning names to worker threads
- */
- private final String workerNamePrefix;
-
- /**
- * Sum of per-thread steal counts, updated only when threads are
- * idle or terminating.
- */
- private volatile long stealCount;
-
- /**
- * Main pool control -- a long packed with:
+ /*
+ * Bits and masks for control variables
+ *
+ * Field ctl is a long packed with:
* AC: Number of active running workers minus target parallelism (16 bits)
* TC: Number of total workers minus target parallelism (16 bits)
* ST: true if pool is terminating (1 bit)
* EC: the wait count of top waiting thread (15 bits)
- * ID: ~poolIndex of top of Treiber stack of waiting threads (16 bits)
+ * ID: poolIndex of top of Treiber stack of waiters (16 bits)
*
* When convenient, we can extract the upper 32 bits of counts and
* the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e =
@@ -483,13 +1149,26 @@
* parallelism and the positionings of fields makes it possible to
* perform the most common checks via sign tests of fields: When
* ac is negative, there are not enough active workers, when tc is
- * negative, there are not enough total workers, when id is
- * negative, there is at least one waiting worker, and when e is
+ * negative, there are not enough total workers, and when e is
* negative, the pool is terminating. To deal with these possibly
* negative fields, we use casts in and out of "short" and/or
* signed shifts to maintain signedness.
+ *
+ * When a thread is queued (inactivated), its eventCount field is
+ * set negative, which is the only way to tell if a worker is
+ * prevented from executing tasks, even though it must continue to
+ * scan for them to avoid queuing races. Note however that
+ * eventCount updates lag releases so usage requires care.
+ *
+ * Field plock is an int packed with:
+ * SHUTDOWN: true if shutdown is enabled (1 bit)
+ * SEQ: a sequence lock, with PL_LOCK bit set if locked (30 bits)
+ * SIGNAL: set when threads may be waiting on the lock (1 bit)
+ *
+ * The sequence number enables simple consistency checks:
+ * Staleness of read-only operations on the workQueues array can
+ * be checked by comparing plock before vs after the reads.
*/
- volatile long ctl;
// bit positions/shifts for fields
private static final int AC_SHIFT = 48;
@@ -498,8 +1177,10 @@
private static final int EC_SHIFT = 16;
// bounds
- private static final int MAX_ID = 0x7fff; // max poolIndex
- private static final int SMASK = 0xffff; // mask short bits
+ private static final int SMASK = 0xffff; // short bits
+ private static final int MAX_CAP = 0x7fff; // max #workers - 1
+ private static final int EVENMASK = 0xfffe; // even short bits
+ private static final int SQMASK = 0x007e; // max 64 (even) slots
private static final int SHORT_SIGN = 1 << 15;
private static final int INT_SIGN = 1 << 31;
@@ -521,648 +1202,648 @@
private static final int UTC_UNIT = 1 << UTC_SHIFT;
// masks and units for dealing with e = (int)ctl
- private static final int E_MASK = 0x7fffffff; // no STOP_BIT
- private static final int EC_UNIT = 1 << EC_SHIFT;
+ private static final int E_MASK = 0x7fffffff; // no STOP_BIT
+ private static final int E_SEQ = 1 << EC_SHIFT;
+
+ // plock bits
+ private static final int SHUTDOWN = 1 << 31;
+ private static final int PL_LOCK = 2;
+ private static final int PL_SIGNAL = 1;
+ private static final int PL_SPINS = 1 << 8;
+
+ // access mode for WorkQueue
+ static final int LIFO_QUEUE = 0;
+ static final int FIFO_QUEUE = 1;
+ static final int SHARED_QUEUE = -1;
+
+ // bounds for #steps in scan loop -- must be power 2 minus 1
+ private static final int MIN_SCAN = 0x1ff; // cover estimation slop
+ private static final int MAX_SCAN = 0x1ffff; // 4 * max workers
+
+ // Instance fields
+
+ /*
+ * Field layout of this class tends to matter more than one would
+ * like. Runtime layout order is only loosely related to
+ * declaration order and may differ across JVMs, but the following
+ * empirically works OK on current JVMs.
+ */
+
+ // Heuristic padding to ameliorate unfortunate memory placements
+ volatile long pad00, pad01, pad02, pad03, pad04, pad05, pad06;
+
+ volatile long stealCount; // collects worker counts
+ volatile long ctl; // main pool control
+ volatile int plock; // shutdown status and seqLock
+ volatile int indexSeed; // worker/submitter index seed
+ final int config; // mode and parallelism level
+ WorkQueue[] workQueues; // main registry
+ final ForkJoinWorkerThreadFactory factory;
+ final Thread.UncaughtExceptionHandler ueh; // per-worker UEH
+ final String workerNamePrefix; // to create worker name string
+
+ volatile Object pad10, pad11, pad12, pad13, pad14, pad15, pad16, pad17;
+ volatile Object pad18, pad19, pad1a, pad1b;
/**
- * The target parallelism level.
+ * Acquires the plock lock to protect worker array and related
+ * updates. This method is called only if an initial CAS on plock
+ * fails. This acts as a spinlock for normal cases, but falls back
+ * to builtin monitor to block when (rarely) needed. This would be
+ * a terrible idea for a highly contended lock, but works fine as
+ * a more conservative alternative to a pure spinlock.
*/
- final int parallelism;
-
- /**
- * Index (mod submission queue length) of next element to take
- * from submission queue. Usage is identical to that for
- * per-worker queues -- see ForkJoinWorkerThread internal
- * documentation.
- */
- volatile int queueBase;
-
- /**
- * Index (mod submission queue length) of next element to add
- * in submission queue. Usage is identical to that for
- * per-worker queues -- see ForkJoinWorkerThread internal
- * documentation.
- */
- int queueTop;
-
- /**
- * True when shutdown() has been called.
- */
- volatile boolean shutdown;
-
- /**
- * True if use local fifo, not default lifo, for local polling.
- * Read by, and replicated by ForkJoinWorkerThreads.
- */
- final boolean locallyFifo;
-
- /**
- * The number of threads in ForkJoinWorkerThreads.helpQuiescePool.
- * When non-zero, suppresses automatic shutdown when active
- * counts become zero.
- */
- volatile int quiescerCount;
-
- /**
- * The number of threads blocked in join.
- */
- volatile int blockedCount;
-
- /**
- * Counter for worker Thread names (unrelated to their poolIndex)
- */
- private volatile int nextWorkerNumber;
-
- /**
- * The index for the next created worker. Accessed under scanGuard.
- */
- private int nextWorkerIndex;
-
- /**
- * SeqLock and index masking for updates to workers array. Locked
- * when SG_UNIT is set. Unlocking clears bit by adding
- * SG_UNIT. Staleness of read-only operations can be checked by
- * comparing scanGuard to value before the reads. The low 16 bits
- * (i.e, anding with SMASK) hold (the smallest power of two
- * covering all worker indices, minus one, and is used to avoid
- * dealing with large numbers of null slots when the workers array
- * is overallocated.
- */
- volatile int scanGuard;
-
- private static final int SG_UNIT = 1 << 16;
-
- /**
- * The wakeup interval (in nanoseconds) for a worker waiting for a
- * task when the pool is quiescent to instead try to shrink the
- * number of workers. The exact value does not matter too
- * much. It must be short enough to release resources during
- * sustained periods of idleness, but not so short that threads
- * are continually re-created.
- */
- private static final long SHRINK_RATE =
- 4L * 1000L * 1000L * 1000L; // 4 seconds
-
- /**
- * Top-level loop for worker threads: On each step: if the
- * previous step swept through all queues and found no tasks, or
- * there are excess threads, then possibly blocks. Otherwise,
- * scans for and, if found, executes a task. Returns when pool
- * and/or worker terminate.
- *
- * @param w the worker
- */
- final void work(ForkJoinWorkerThread w) {
- boolean swept = false; // true on empty scans
- long c;
- while (!w.terminate && (int)(c = ctl) >= 0) {
- int a; // active count
- if (!swept && (a = (int)(c >> AC_SHIFT)) <= 0)
- swept = scan(w, a);
- else if (tryAwaitWork(w, c))
- swept = false;
+ private int acquirePlock() {
+ int spins = PL_SPINS, r = 0, ps, nps;
+ for (;;) {
+ if (((ps = plock) & PL_LOCK) == 0 &&
+ U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK))
+ return nps;
+ else if (r == 0) { // randomize spins if possible
+ Thread t = Thread.currentThread(); WorkQueue w; Submitter z;
+ if ((t instanceof ForkJoinWorkerThread) &&
+ (w = ((ForkJoinWorkerThread)t).workQueue) != null)
+ r = w.seed;
+ else if ((z = submitters.get()) != null)
+ r = z.seed;
+ else
+ r = 1;
+ }
+ else if (spins >= 0) {
+ r ^= r << 1; r ^= r >>> 3; r ^= r << 10; // xorshift
+ if (r >= 0)
+ --spins;
+ }
+ else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) {
+ synchronized (this) {
+ if ((plock & PL_SIGNAL) != 0) {
+ try {
+ wait();
+ } catch (InterruptedException ie) {
+ try {
+ Thread.currentThread().interrupt();
+ } catch (SecurityException ignore) {
+ }
+ }
+ }
+ else
+ notifyAll();
+ }
+ }
}
}
- // Signalling
+ /**
+ * Unlocks and signals any thread waiting for plock. Called only
+ * when CAS of seq value for unlock fails.
+ */
+ private void releasePlock(int ps) {
+ plock = ps;
+ synchronized (this) { notifyAll(); }
+ }
/**
- * Wakes up or creates a worker.
+ * Performs secondary initialization, called when plock is zero.
+ * Creates workQueue array and sets plock to a valid value. The
+ * lock body must be exception-free (so no try/finally) so we
+ * optimistically allocate new array outside the lock and throw
+ * away if (very rarely) not needed. (A similar tactic is used in
+ * fullExternalPush.) Because the plock seq value can eventually
+ * wrap around zero, this method harmlessly fails to reinitialize
+ * if workQueues exists, while still advancing plock.
+ *
+ * Additionally tries to create the first worker.
*/
- final void signalWork() {
- /*
- * The while condition is true if: (there is are too few total
- * workers OR there is at least one waiter) AND (there are too
- * few active workers OR the pool is terminating). The value
- * of e distinguishes the remaining cases: zero (no waiters)
- * for create, negative if terminating (in which case do
- * nothing), else release a waiter. The secondary checks for
- * release (non-null array etc) can fail if the pool begins
- * terminating after the test, and don't impose any added cost
- * because JVMs must perform null and bounds checks anyway.
- */
- long c; int e, u;
- while ((((e = (int)(c = ctl)) | (u = (int)(c >>> 32))) &
- (INT_SIGN|SHORT_SIGN)) == (INT_SIGN|SHORT_SIGN) && e >= 0) {
- if (e > 0) { // release a waiting worker
- int i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
- if ((ws = workers) == null ||
- (i = ~e & SMASK) >= ws.length ||
- (w = ws[i]) == null)
- break;
- long nc = (((long)(w.nextWait & E_MASK)) |
- ((long)(u + UAC_UNIT) << 32));
- if (w.eventCount == e &&
- UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
- w.eventCount = (e + EC_UNIT) & E_MASK;
- if (w.parked)
- UNSAFE.unpark(w);
- break;
+ private void initWorkers() {
+ WorkQueue[] ws, nws; int ps;
+ int p = config & SMASK; // find power of two table size
+ int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
+ n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+ n = (n + 1) << 1;
+ if ((ws = workQueues) == null || ws.length == 0)
+ nws = new WorkQueue[n];
+ else
+ nws = null;
+ if (((ps = plock) & PL_LOCK) != 0 ||
+ !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+ ps = acquirePlock();
+ if (((ws = workQueues) == null || ws.length == 0) && nws != null)
+ workQueues = nws;
+ int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+ if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+ releasePlock(nps);
+ tryAddWorker();
+ }
+
+ /**
+ * Tries to create and start one worker if fewer than target
+ * parallelism level exist. Adjusts counts etc on failure.
+ */
+ private void tryAddWorker() {
+ long c; int u;
+ while ((u = (int)((c = ctl) >>> 32)) < 0 &&
+ (u & SHORT_SIGN) != 0 && (int)c == 0) {
+ long nc = (long)(((u + UTC_UNIT) & UTC_MASK) |
+ ((u + UAC_UNIT) & UAC_MASK)) << 32;
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ ForkJoinWorkerThreadFactory fac;
+ Throwable ex = null;
+ ForkJoinWorkerThread wt = null;
+ try {
+ if ((fac = factory) != null &&
+ (wt = fac.newThread(this)) != null) {
+ wt.start();
+ break;
+ }
+ } catch (Throwable e) {
+ ex = e;
}
- }
- else if (UNSAFE.compareAndSwapLong
- (this, ctlOffset, c,
- (long)(((u + UTC_UNIT) & UTC_MASK) |
- ((u + UAC_UNIT) & UAC_MASK)) << 32)) {
- addWorker();
+ deregisterWorker(wt, ex);
break;
}
}
}
- /**
- * Variant of signalWork to help release waiters on rescans.
- * Tries once to release a waiter if active count < 0.
- *
- * @return false if failed due to contention, else true
- */
- private boolean tryReleaseWaiter() {
- long c; int e, i; ForkJoinWorkerThread w; ForkJoinWorkerThread[] ws;
- if ((e = (int)(c = ctl)) > 0 &&
- (int)(c >> AC_SHIFT) < 0 &&
- (ws = workers) != null &&
- (i = ~e & SMASK) < ws.length &&
- (w = ws[i]) != null) {
- long nc = ((long)(w.nextWait & E_MASK) |
- ((c + AC_UNIT) & (AC_MASK|TC_MASK)));
- if (w.eventCount != e ||
- !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
- return false;
- w.eventCount = (e + EC_UNIT) & E_MASK;
- if (w.parked)
- UNSAFE.unpark(w);
- }
- return true;
- }
-
- // Scanning for tasks
+ // Registering and deregistering workers
/**
- * Scans for and, if found, executes one task. Scans start at a
- * random index of workers array, and randomly select the first
- * (2*#workers)-1 probes, and then, if all empty, resort to 2
- * circular sweeps, which is necessary to check quiescence. and
- * taking a submission only if no stealable tasks were found. The
- * steal code inside the loop is a specialized form of
- * ForkJoinWorkerThread.deqTask, followed bookkeeping to support
- * helpJoinTask and signal propagation. The code for submission
- * queues is almost identical. On each steal, the worker completes
- * not only the task, but also all local tasks that this task may
- * have generated. On detecting staleness or contention when
- * trying to take a task, this method returns without finishing
- * sweep, which allows global state rechecks before retry.
+ * Callback from ForkJoinWorkerThread to establish and record its
+ * WorkQueue. To avoid scanning bias due to packing entries in
+ * front of the workQueues array, we treat the array as a simple
+ * power-of-two hash table using per-thread seed as hash,
+ * expanding as needed.
*
- * @param w the worker
- * @param a the number of active workers
- * @return true if swept all queues without finding a task
+ * @param wt the worker thread
+ * @return the worker's queue
*/
- private boolean scan(ForkJoinWorkerThread w, int a) {
- int g = scanGuard; // mask 0 avoids useless scans if only one active
- int m = (parallelism == 1 - a && blockedCount == 0) ? 0 : g & SMASK;
- ForkJoinWorkerThread[] ws = workers;
- if (ws == null || ws.length <= m) // staleness check
- return false;
- for (int r = w.seed, k = r, j = -(m + m); j <= m + m; ++j) {
- ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
- ForkJoinWorkerThread v = ws[k & m];
- if (v != null && (b = v.queueBase) != v.queueTop &&
- (q = v.queue) != null && (i = (q.length - 1) & b) >= 0) {
- long u = (i << ASHIFT) + ABASE;
- if ((t = q[i]) != null && v.queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- int d = (v.queueBase = b + 1) - v.queueTop;
- v.stealHint = w.poolIndex;
- if (d != 0)
- signalWork(); // propagate if nonempty
- w.execTask(t);
- }
- r ^= r << 13; r ^= r >>> 17; w.seed = r ^ (r << 5);
- return false; // store next seed
- }
- else if (j < 0) { // xorshift
- r ^= r << 13; r ^= r >>> 17; k = r ^= r << 5;
- }
- else
- ++k;
- }
- if (scanGuard != g) // staleness check
- return false;
- else { // try to take submission
- ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
- if ((b = queueBase) != queueTop &&
- (q = submissionQueue) != null &&
- (i = (q.length - 1) & b) >= 0) {
- long u = (i << ASHIFT) + ABASE;
- if ((t = q[i]) != null && queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- queueBase = b + 1;
- w.execTask(t);
- }
- return false;
- }
- return true; // all queues empty
- }
- }
-
- /**
- * Tries to enqueue worker w in wait queue and await change in
- * worker's eventCount. If the pool is quiescent and there is
- * more than one worker, possibly terminates worker upon exit.
- * Otherwise, before blocking, rescans queues to avoid missed
- * signals. Upon finding work, releases at least one worker
- * (which may be the current worker). Rescans restart upon
- * detected staleness or failure to release due to
- * contention. Note the unusual conventions about Thread.interrupt
- * here and elsewhere: Because interrupts are used solely to alert
- * threads to check termination, which is checked here anyway, we
- * clear status (using Thread.interrupted) before any call to
- * park, so that park does not immediately return due to status
- * being set via some other unrelated call to interrupt in user
- * code.
- *
- * @param w the calling worker
- * @param c the ctl value on entry
- * @return true if waited or another thread was released upon enq
- */
- private boolean tryAwaitWork(ForkJoinWorkerThread w, long c) {
- int v = w.eventCount;
- w.nextWait = (int)c; // w's successor record
- long nc = (long)(v & E_MASK) | ((c - AC_UNIT) & (AC_MASK|TC_MASK));
- if (ctl != c || !UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
- long d = ctl; // return true if lost to a deq, to force scan
- return (int)d != (int)c && (d & AC_MASK) >= (c & AC_MASK);
- }
- for (int sc = w.stealCount; sc != 0;) { // accumulate stealCount
- long s = stealCount;
- if (UNSAFE.compareAndSwapLong(this, stealCountOffset, s, s + sc))
- sc = w.stealCount = 0;
- else if (w.eventCount != v)
- return true; // update next time
- }
- if ((!shutdown || !tryTerminate(false)) &&
- (int)c != 0 && parallelism + (int)(nc >> AC_SHIFT) == 0 &&
- blockedCount == 0 && quiescerCount == 0)
- idleAwaitWork(w, nc, c, v); // quiescent
- for (boolean rescanned = false;;) {
- if (w.eventCount != v)
- return true;
- if (!rescanned) {
- int g = scanGuard, m = g & SMASK;
- ForkJoinWorkerThread[] ws = workers;
- if (ws != null && m < ws.length) {
- rescanned = true;
- for (int i = 0; i <= m; ++i) {
- ForkJoinWorkerThread u = ws[i];
- if (u != null) {
- if (u.queueBase != u.queueTop &&
- !tryReleaseWaiter())
- rescanned = false; // contended
- if (w.eventCount != v)
- return true;
+ final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
+ Thread.UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps;
+ wt.setDaemon(true);
+ if ((handler = ueh) != null)
+ wt.setUncaughtExceptionHandler(handler);
+ do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed,
+ s += SEED_INCREMENT) ||
+ s == 0); // skip 0
+ WorkQueue w = new WorkQueue(this, wt, config >>> 16, s);
+ if (((ps = plock) & PL_LOCK) != 0 ||
+ !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+ ps = acquirePlock();
+ int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+ try {
+ if ((ws = workQueues) != null) { // skip if shutting down
+ int n = ws.length, m = n - 1;
+ int r = (s << 1) | 1; // use odd-numbered indices
+ if (ws[r &= m] != null) { // collision
+ int probes = 0; // step by approx half size
+ int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
+ while (ws[r = (r + step) & m] != null) {
+ if (++probes >= n) {
+ workQueues = ws = Arrays.copyOf(ws, n <<= 1);
+ m = n - 1;
+ probes = 0;
}
}
}
- if (scanGuard != g || // stale
- (queueBase != queueTop && !tryReleaseWaiter()))
- rescanned = false;
- if (!rescanned)
- Thread.yield(); // reduce contention
- else
- Thread.interrupted(); // clear before park
+ w.eventCount = w.poolIndex = r; // volatile write orders
+ ws[r] = w;
}
- else {
- w.parked = true; // must recheck
- if (w.eventCount != v) {
- w.parked = false;
- return true;
- }
- LockSupport.park(this);
- rescanned = w.parked = false;
- }
+ } finally {
+ if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+ releasePlock(nps);
}
+ wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex)));
+ return w;
}
/**
- * If inactivating worker w has caused pool to become
- * quiescent, check for pool termination, and wait for event
- * for up to SHRINK_RATE nanosecs (rescans are unnecessary in
- * this case because quiescence reflects consensus about lack
- * of work). On timeout, if ctl has not changed, terminate the
- * worker. Upon its termination (see deregisterWorker), it may
- * wake up another worker to possibly repeat this process.
+ * Final callback from terminating worker, as well as upon failure
+ * to construct or start a worker. Removes record of worker from
+ * array, and adjusts counts. If pool is shutting down, tries to
+ * complete termination.
*
- * @param w the calling worker
- * @param currentCtl the ctl value after enqueuing w
- * @param prevCtl the ctl value if w terminated
- * @param v the eventCount w awaits change
+ * @param wt the worker thread or null if construction failed
+ * @param ex the exception causing failure, or null if none
*/
- private void idleAwaitWork(ForkJoinWorkerThread w, long currentCtl,
- long prevCtl, int v) {
- if (w.eventCount == v) {
- if (shutdown)
- tryTerminate(false);
- ForkJoinTask.helpExpungeStaleExceptions(); // help clean weak refs
- while (ctl == currentCtl) {
- long startTime = System.nanoTime();
- w.parked = true;
- if (w.eventCount == v) // must recheck
- LockSupport.parkNanos(this, SHRINK_RATE);
- w.parked = false;
- if (w.eventCount != v)
- break;
- else if (System.nanoTime() - startTime <
- SHRINK_RATE - (SHRINK_RATE / 10)) // timing slop
- Thread.interrupted(); // spurious wakeup
- else if (UNSAFE.compareAndSwapLong(this, ctlOffset,
- currentCtl, prevCtl)) {
- w.terminate = true; // restore previous
- w.eventCount = ((int)currentCtl + EC_UNIT) & E_MASK;
+ final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
+ WorkQueue w = null;
+ if (wt != null && (w = wt.workQueue) != null) {
+ int ps;
+ w.qlock = -1; // ensure set
+ long ns = w.nsteals, sc; // collect steal count
+ do {} while (!U.compareAndSwapLong(this, STEALCOUNT,
+ sc = stealCount, sc + ns));
+ if (((ps = plock) & PL_LOCK) != 0 ||
+ !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+ ps = acquirePlock();
+ int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+ try {
+ int idx = w.poolIndex;
+ WorkQueue[] ws = workQueues;
+ if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w)
+ ws[idx] = null;
+ } finally {
+ if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+ releasePlock(nps);
+ }
+ }
+
+ long c; // adjust ctl counts
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) |
+ ((c - TC_UNIT) & TC_MASK) |
+ (c & ~(AC_MASK|TC_MASK)))));
+
+ if (!tryTerminate(false, false) && w != null && w.array != null) {
+ w.cancelAll(); // cancel remaining tasks
+ WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e;
+ while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) {
+ if (e > 0) { // activate or create replacement
+ if ((ws = workQueues) == null ||
+ (i = e & SMASK) >= ws.length ||
+ (v = ws[i]) != null)
+ break;
+ long nc = (((long)(v.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT) << 32));
+ if (v.eventCount != (e | INT_SIGN))
+ break;
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ v.eventCount = (e + E_SEQ) & E_MASK;
+ if ((p = v.parker) != null)
+ U.unpark(p);
+ break;
+ }
+ }
+ else {
+ if ((short)u < 0)
+ tryAddWorker();
break;
}
}
}
+ if (ex == null) // help clean refs on way out
+ ForkJoinTask.helpExpungeStaleExceptions();
+ else // rethrow
+ ForkJoinTask.rethrow(ex);
}
// Submissions
/**
- * Enqueues the given task in the submissionQueue. Same idea as
- * ForkJoinWorkerThread.pushTask except for use of submissionLock.
+ * Unless shutting down, adds the given task to a submission queue
+ * at submitter's current queue index (modulo submission
+ * range). Only the most common path is directly handled in this
+ * method. All others are relayed to fullExternalPush.
*
- * @param t the task
+ * @param task the task. Caller must ensure non-null.
*/
- private void addSubmission(ForkJoinTask<?> t) {
- final ReentrantLock lock = this.submissionLock;
- lock.lock();
- try {
- ForkJoinTask<?>[] q; int s, m;
- if ((q = submissionQueue) != null) { // ignore if queue removed
- long u = (((s = queueTop) & (m = q.length-1)) << ASHIFT)+ABASE;
- UNSAFE.putOrderedObject(q, u, t);
- queueTop = s + 1;
- if (s - queueBase == m)
- growSubmissionQueue();
+ final void externalPush(ForkJoinTask<?> task) {
+ WorkQueue[] ws; WorkQueue q; Submitter z; int m; ForkJoinTask<?>[] a;
+ if ((z = submitters.get()) != null && plock > 0 &&
+ (ws = workQueues) != null && (m = (ws.length - 1)) >= 0 &&
+ (q = ws[m & z.seed & SQMASK]) != null &&
+ U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock
+ int b = q.base, s = q.top, n, an;
+ if ((a = q.array) != null && (an = a.length) > (n = s + 1 - b)) {
+ int j = (((an - 1) & s) << ASHIFT) + ABASE;
+ U.putOrderedObject(a, j, task);
+ q.top = s + 1; // push on to deque
+ q.qlock = 0;
+ if (n <= 2)
+ signalWork(q);
+ return;
}
- } finally {
- lock.unlock();
+ q.qlock = 0;
}
- signalWork();
+ fullExternalPush(task);
}
- // (pollSubmission is defined below with exported methods)
-
/**
- * Creates or doubles submissionQueue array.
- * Basically identical to ForkJoinWorkerThread version.
+ * Full version of externalPush. This method is called, among
+ * other times, upon the first submission of the first task to the
+ * pool, so must perform secondary initialization (via
+ * initWorkers). It also detects first submission by an external
+ * thread by looking up its ThreadLocal, and creates a new shared
+ * queue if the one at index if empty or contended. The plock lock
+ * body must be exception-free (so no try/finally) so we
+ * optimistically allocate new queues outside the lock and throw
+ * them away if (very rarely) not needed.
*/
- private void growSubmissionQueue() {
- ForkJoinTask<?>[] oldQ = submissionQueue;
- int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
- if (size > MAXIMUM_QUEUE_CAPACITY)
- throw new RejectedExecutionException("Queue capacity exceeded");
- if (size < INITIAL_QUEUE_CAPACITY)
- size = INITIAL_QUEUE_CAPACITY;
- ForkJoinTask<?>[] q = submissionQueue = new ForkJoinTask<?>[size];
- int mask = size - 1;
- int top = queueTop;
- int oldMask;
- if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
- for (int b = queueBase; b != top; ++b) {
- long u = ((b & oldMask) << ASHIFT) + ABASE;
- Object x = UNSAFE.getObjectVolatile(oldQ, u);
- if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
- UNSAFE.putObjectVolatile
- (q, ((b & mask) << ASHIFT) + ABASE, x);
+ private void fullExternalPush(ForkJoinTask<?> task) {
+ int r = 0; // random index seed
+ for (Submitter z = submitters.get();;) {
+ WorkQueue[] ws; WorkQueue q; int ps, m, k;
+ if (z == null) {
+ if (U.compareAndSwapInt(this, INDEXSEED, r = indexSeed,
+ r += SEED_INCREMENT) && r != 0)
+ submitters.set(z = new Submitter(r));
}
- }
- }
-
- // Blocking support
-
- /**
- * Tries to increment blockedCount, decrement active count
- * (sometimes implicitly) and possibly release or create a
- * compensating worker in preparation for blocking. Fails
- * on contention or termination.
- *
- * @return true if the caller can block, else should recheck and retry
- */
- private boolean tryPreBlock() {
- int b = blockedCount;
- if (UNSAFE.compareAndSwapInt(this, blockedCountOffset, b, b + 1)) {
- int pc = parallelism;
- do {
- ForkJoinWorkerThread[] ws; ForkJoinWorkerThread w;
- int e, ac, tc, i;
- long c = ctl;
- int u = (int)(c >>> 32);
- if ((e = (int)c) < 0) {
- // skip -- terminating
- }
- else if ((ac = (u >> UAC_SHIFT)) <= 0 && e != 0 &&
- (ws = workers) != null &&
- (i = ~e & SMASK) < ws.length &&
- (w = ws[i]) != null) {
- long nc = ((long)(w.nextWait & E_MASK) |
- (c & (AC_MASK|TC_MASK)));
- if (w.eventCount == e &&
- UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
- w.eventCount = (e + EC_UNIT) & E_MASK;
- if (w.parked)
- UNSAFE.unpark(w);
- return true; // release an idle worker
- }
- }
- else if ((tc = (short)(u >>> UTC_SHIFT)) >= 0 && ac + pc > 1) {
- long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
- if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc))
- return true; // no compensation needed
- }
- else if (tc + pc < MAX_ID) {
- long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
- if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, nc)) {
- addWorker();
- return true; // create a replacement
- }
- }
- // try to back out on any failure and let caller retry
- } while (!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
- b = blockedCount, b - 1));
- }
- return false;
- }
-
- /**
- * Decrements blockedCount and increments active count.
- */
- private void postBlock() {
- long c;
- do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset, // no mask
- c = ctl, c + AC_UNIT));
- int b;
- do {} while (!UNSAFE.compareAndSwapInt(this, blockedCountOffset,
- b = blockedCount, b - 1));
- }
-
- /**
- * Possibly blocks waiting for the given task to complete, or
- * cancels the task if terminating. Fails to wait if contended.
- *
- * @param joinMe the task
- */
- final void tryAwaitJoin(ForkJoinTask<?> joinMe) {
- Thread.interrupted(); // clear interrupts before checking termination
- if (joinMe.status >= 0) {
- if (tryPreBlock()) {
- joinMe.tryAwaitDone(0L);
- postBlock();
+ else if (r == 0) { // move to a different index
+ r = z.seed;
+ r ^= r << 13; // same xorshift as WorkQueues
+ r ^= r >>> 17;
+ z.seed = r ^ (r << 5);
}
- else if ((ctl & STOP_BIT) != 0L)
- joinMe.cancelIgnoringExceptions();
- }
- }
-
- /**
- * Possibly blocks the given worker waiting for joinMe to
- * complete or timeout.
- *
- * @param joinMe the task
- * @param nanos the wait time for underlying Object.wait
- */
- final void timedAwaitJoin(ForkJoinTask<?> joinMe, long nanos) {
- while (joinMe.status >= 0) {
- Thread.interrupted();
- if ((ctl & STOP_BIT) != 0L) {
- joinMe.cancelIgnoringExceptions();
- break;
- }
- if (tryPreBlock()) {
- long last = System.nanoTime();
- while (joinMe.status >= 0) {
- long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
- if (millis <= 0)
- break;
- joinMe.tryAwaitDone(millis);
- if (joinMe.status < 0)
- break;
- if ((ctl & STOP_BIT) != 0L) {
- joinMe.cancelIgnoringExceptions();
- break;
- }
- long now = System.nanoTime();
- nanos -= now - last;
- last = now;
- }
- postBlock();
- break;
- }
- }
- }
-
- /**
- * If necessary, compensates for blocker, and blocks.
- */
- private void awaitBlocker(ManagedBlocker blocker)
- throws InterruptedException {
- while (!blocker.isReleasable()) {
- if (tryPreBlock()) {
- try {
- do {} while (!blocker.isReleasable() && !blocker.block());
- } finally {
- postBlock();
- }
- break;
- }
- }
- }
-
- // Creating, registering and deregistring workers
-
- /**
- * Tries to create and start a worker; minimally rolls back counts
- * on failure.
- */
- private void addWorker() {
- Throwable ex = null;
- ForkJoinWorkerThread t = null;
- try {
- t = factory.newThread(this);
- } catch (Throwable e) {
- ex = e;
- }
- if (t == null) { // null or exceptional factory return
- long c; // adjust counts
- do {} while (!UNSAFE.compareAndSwapLong
- (this, ctlOffset, c = ctl,
- (((c - AC_UNIT) & AC_MASK) |
- ((c - TC_UNIT) & TC_MASK) |
- (c & ~(AC_MASK|TC_MASK)))));
- // Propagate exception if originating from an external caller
- if (!tryTerminate(false) && ex != null &&
- !(Thread.currentThread() instanceof ForkJoinWorkerThread))
- SneakyThrow.sneakyThrow(ex); // android-changed
- }
- else
- t.start();
- }
-
- /**
- * Callback from ForkJoinWorkerThread constructor to assign a
- * public name
- */
- final String nextWorkerName() {
- for (int n;;) {
- if (UNSAFE.compareAndSwapInt(this, nextWorkerNumberOffset,
- n = nextWorkerNumber, ++n))
- return workerNamePrefix + n;
- }
- }
-
- /**
- * Callback from ForkJoinWorkerThread constructor to
- * determine its poolIndex and record in workers array.
- *
- * @param w the worker
- * @return the worker's pool index
- */
- final int registerWorker(ForkJoinWorkerThread w) {
- /*
- * In the typical case, a new worker acquires the lock, uses
- * next available index and returns quickly. Since we should
- * not block callers (ultimately from signalWork or
- * tryPreBlock) waiting for the lock needed to do this, we
- * instead help release other workers while waiting for the
- * lock.
- */
- for (int g;;) {
- ForkJoinWorkerThread[] ws;
- if (((g = scanGuard) & SG_UNIT) == 0 &&
- UNSAFE.compareAndSwapInt(this, scanGuardOffset,
- g, g | SG_UNIT)) {
- int k = nextWorkerIndex;
- try {
- if ((ws = workers) != null) { // ignore on shutdown
- int n = ws.length;
- if (k < 0 || k >= n || ws[k] != null) {
- for (k = 0; k < n && ws[k] != null; ++k)
- ;
- if (k == n)
- ws = workers = Arrays.copyOf(ws, n << 1);
+ else if ((ps = plock) < 0)
+ throw new RejectedExecutionException();
+ else if (ps == 0 || (ws = workQueues) == null ||
+ (m = ws.length - 1) < 0)
+ initWorkers();
+ else if ((q = ws[k = r & m & SQMASK]) != null) {
+ if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+ ForkJoinTask<?>[] a = q.array;
+ int s = q.top;
+ boolean submitted = false;
+ try { // locked version of push
+ if ((a != null && a.length > s + 1 - q.base) ||
+ (a = q.growArray()) != null) { // must presize
+ int j = (((a.length - 1) & s) << ASHIFT) + ABASE;
+ U.putOrderedObject(a, j, task);
+ q.top = s + 1;
+ submitted = true;
}
- ws[k] = w;
- nextWorkerIndex = k + 1;
- int m = g & SMASK;
- g = (k > m) ? ((m << 1) + 1) & SMASK : g + (SG_UNIT<<1);
+ } finally {
+ q.qlock = 0; // unlock
}
- } finally {
- scanGuard = g;
+ if (submitted) {
+ signalWork(q);
+ return;
+ }
}
- return k;
+ r = 0; // move on failure
}
- else if ((ws = workers) != null) { // help release others
- for (ForkJoinWorkerThread u : ws) {
- if (u != null && u.queueBase != u.queueTop) {
- if (tryReleaseWaiter())
+ else if (((ps = plock) & PL_LOCK) == 0) { // create new queue
+ q = new WorkQueue(this, null, SHARED_QUEUE, r);
+ if (((ps = plock) & PL_LOCK) != 0 ||
+ !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+ ps = acquirePlock();
+ if ((ws = workQueues) != null && k < ws.length && ws[k] == null)
+ ws[k] = q;
+ int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN);
+ if (!U.compareAndSwapInt(this, PLOCK, ps, nps))
+ releasePlock(nps);
+ }
+ else
+ r = 0; // try elsewhere while lock held
+ }
+ }
+
+ // Maintaining ctl counts
+
+ /**
+ * Increments active count; mainly called upon return from blocking.
+ */
+ final void incrementActiveCount() {
+ long c;
+ do {} while (!U.compareAndSwapLong(this, CTL, c = ctl, c + AC_UNIT));
+ }
+
+ /**
+ * Tries to create or activate a worker if too few are active.
+ *
+ * @param q the (non-null) queue holding tasks to be signalled
+ */
+ final void signalWork(WorkQueue q) {
+ int hint = q.poolIndex;
+ long c; int e, u, i, n; WorkQueue[] ws; WorkQueue w; Thread p;
+ while ((u = (int)((c = ctl) >>> 32)) < 0) {
+ if ((e = (int)c) > 0) {
+ if ((ws = workQueues) != null && ws.length > (i = e & SMASK) &&
+ (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
+ long nc = (((long)(w.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT) << 32));
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ w.hint = hint;
+ w.eventCount = (e + E_SEQ) & E_MASK;
+ if ((p = w.parker) != null)
+ U.unpark(p);
+ break;
+ }
+ if (q.top - q.base <= 0)
+ break;
+ }
+ else
+ break;
+ }
+ else {
+ if ((short)u < 0)
+ tryAddWorker();
+ break;
+ }
+ }
+ }
+
+ // Scanning for tasks
+
+ /**
+ * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
+ */
+ final void runWorker(WorkQueue w) {
+ w.growArray(); // allocate queue
+ do { w.runTask(scan(w)); } while (w.qlock >= 0);
+ }
+
+ /**
+ * Scans for and, if found, returns one task, else possibly
+ * inactivates the worker. This method operates on single reads of
+ * volatile state and is designed to be re-invoked continuously,
+ * in part because it returns upon detecting inconsistencies,
+ * contention, or state changes that indicate possible success on
+ * re-invocation.
+ *
+ * The scan searches for tasks across queues (starting at a random
+ * index, and relying on registerWorker to irregularly scatter
+ * them within array to avoid bias), checking each at least twice.
+ * The scan terminates upon either finding a non-empty queue, or
+ * completing the sweep. If the worker is not inactivated, it
+ * takes and returns a task from this queue. Otherwise, if not
+ * activated, it signals workers (that may include itself) and
+ * returns so caller can retry. Also returns for true if the
+ * worker array may have changed during an empty scan. On failure
+ * to find a task, we take one of the following actions, after
+ * which the caller will retry calling this method unless
+ * terminated.
+ *
+ * * If pool is terminating, terminate the worker.
+ *
+ * * If not already enqueued, try to inactivate and enqueue the
+ * worker on wait queue. Or, if inactivating has caused the pool
+ * to be quiescent, relay to idleAwaitWork to possibly shrink
+ * pool.
+ *
+ * * If already enqueued and none of the above apply, possibly
+ * park awaiting signal, else lingering to help scan and signal.
+ *
+ * * If a non-empty queue discovered or left as a hint,
+ * help wake up other workers before return.
+ *
+ * @param w the worker (via its WorkQueue)
+ * @return a task or null if none found
+ */
+ private final ForkJoinTask<?> scan(WorkQueue w) {
+ WorkQueue[] ws; int m;
+ int ps = plock; // read plock before ws
+ if (w != null && (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+ int ec = w.eventCount; // ec is negative if inactive
+ int r = w.seed; r ^= r << 13; r ^= r >>> 17; w.seed = r ^= r << 5;
+ w.hint = -1; // update seed and clear hint
+ int j = ((m + m + 1) | MIN_SCAN) & MAX_SCAN;
+ do {
+ WorkQueue q; ForkJoinTask<?>[] a; int b;
+ if ((q = ws[(r + j) & m]) != null && (b = q.base) - q.top < 0 &&
+ (a = q.array) != null) { // probably nonempty
+ int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ ForkJoinTask<?> t = (ForkJoinTask<?>)
+ U.getObjectVolatile(a, i);
+ if (q.base == b && ec >= 0 && t != null &&
+ U.compareAndSwapObject(a, i, t, null)) {
+ if ((q.base = b + 1) - q.top < 0)
+ signalWork(q);
+ return t; // taken
+ }
+ else if ((ec < 0 || j < m) && (int)(ctl >> AC_SHIFT) <= 0) {
+ w.hint = (r + j) & m; // help signal below
+ break; // cannot take
+ }
+ }
+ } while (--j >= 0);
+
+ int h, e, ns; long c, sc; WorkQueue q;
+ if ((ns = w.nsteals) != 0) {
+ if (U.compareAndSwapLong(this, STEALCOUNT,
+ sc = stealCount, sc + ns))
+ w.nsteals = 0; // collect steals and rescan
+ }
+ else if (plock != ps) // consistency check
+ ; // skip
+ else if ((e = (int)(c = ctl)) < 0)
+ w.qlock = -1; // pool is terminating
+ else {
+ if ((h = w.hint) < 0) {
+ if (ec >= 0) { // try to enqueue/inactivate
+ long nc = (((long)ec |
+ ((c - AC_UNIT) & (AC_MASK|TC_MASK))));
+ w.nextWait = e; // link and mark inactive
+ w.eventCount = ec | INT_SIGN;
+ if (ctl != c || !U.compareAndSwapLong(this, CTL, c, nc))
+ w.eventCount = ec; // unmark on CAS failure
+ else if ((int)(c >> AC_SHIFT) == 1 - (config & SMASK))
+ idleAwaitWork(w, nc, c);
+ }
+ else if (w.eventCount < 0 && !tryTerminate(false, false) &&
+ ctl == c) { // block
+ Thread wt = Thread.currentThread();
+ Thread.interrupted(); // clear status
+ U.putObject(wt, PARKBLOCKER, this);
+ w.parker = wt; // emulate LockSupport.park
+ if (w.eventCount < 0) // recheck
+ U.park(false, 0L);
+ w.parker = null;
+ U.putObject(wt, PARKBLOCKER, null);
+ }
+ }
+ if ((h >= 0 || (h = w.hint) >= 0) &&
+ (ws = workQueues) != null && h < ws.length &&
+ (q = ws[h]) != null) { // signal others before retry
+ WorkQueue v; Thread p; int u, i, s;
+ for (int n = (config & SMASK) >>> 1;;) {
+ int idleCount = (w.eventCount < 0) ? 0 : -1;
+ if (((s = idleCount - q.base + q.top) <= n &&
+ (n = s) <= 0) ||
+ (u = (int)((c = ctl) >>> 32)) >= 0 ||
+ (e = (int)c) <= 0 || m < (i = e & SMASK) ||
+ (v = ws[i]) == null)
+ break;
+ long nc = (((long)(v.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT) << 32));
+ if (v.eventCount != (e | INT_SIGN) ||
+ !U.compareAndSwapLong(this, CTL, c, nc))
+ break;
+ v.hint = h;
+ v.eventCount = (e + E_SEQ) & E_MASK;
+ if ((p = v.parker) != null)
+ U.unpark(p);
+ if (--n <= 0)
+ break;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * If inactivating worker w has caused the pool to become
+ * quiescent, checks for pool termination, and, so long as this is
+ * not the only worker, waits for event for up to a given
+ * duration. On timeout, if ctl has not changed, terminates the
+ * worker, which will in turn wake up another worker to possibly
+ * repeat this process.
+ *
+ * @param w the calling worker
+ * @param currentCtl the ctl value triggering possible quiescence
+ * @param prevCtl the ctl value to restore if thread is terminated
+ */
+ private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
+ if (w != null && w.eventCount < 0 &&
+ !tryTerminate(false, false) && (int)prevCtl != 0) {
+ int dc = -(short)(currentCtl >>> TC_SHIFT);
+ long parkTime = dc < 0 ? FAST_IDLE_TIMEOUT: (dc + 1) * IDLE_TIMEOUT;
+ long deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP;
+ Thread wt = Thread.currentThread();
+ while (ctl == currentCtl) {
+ Thread.interrupted(); // timed variant of version in scan()
+ U.putObject(wt, PARKBLOCKER, this);
+ w.parker = wt;
+ if (ctl == currentCtl)
+ U.park(false, parkTime);
+ w.parker = null;
+ U.putObject(wt, PARKBLOCKER, null);
+ if (ctl != currentCtl)
+ break;
+ if (deadline - System.nanoTime() <= 0L &&
+ U.compareAndSwapLong(this, CTL, currentCtl, prevCtl)) {
+ w.eventCount = (w.eventCount + E_SEQ) | E_MASK;
+ w.qlock = -1; // shrink
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Scans through queues looking for work while joining a task; if
+ * any present, signals. May return early if more signalling is
+ * detectably unneeded.
+ *
+ * @param task return early if done
+ * @param origin an index to start scan
+ */
+ private void helpSignal(ForkJoinTask<?> task, int origin) {
+ WorkQueue[] ws; WorkQueue w; Thread p; long c; int m, u, e, i, s;
+ if (task != null && task.status >= 0 &&
+ (u = (int)(ctl >>> 32)) < 0 && (u >> UAC_SHIFT) < 0 &&
+ (ws = workQueues) != null && (m = ws.length - 1) >= 0) {
+ outer: for (int k = origin, j = m; j >= 0; --j) {
+ WorkQueue q = ws[k++ & m];
+ for (int n = m;;) { // limit to at most m signals
+ if (task.status < 0)
+ break outer;
+ if (q == null ||
+ ((s = -q.base + q.top) <= n && (n = s) <= 0))
+ break;
+ if ((u = (int)((c = ctl) >>> 32)) >= 0 ||
+ (e = (int)c) <= 0 || m < (i = e & SMASK) ||
+ (w = ws[i]) == null)
+ break outer;
+ long nc = (((long)(w.nextWait & E_MASK)) |
+ ((long)(u + UAC_UNIT) << 32));
+ if (w.eventCount != (e | INT_SIGN))
+ break outer;
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ w.eventCount = (e + E_SEQ) & E_MASK;
+ if ((p = w.parker) != null)
+ U.unpark(p);
+ if (--n <= 0)
break;
}
}
@@ -1171,201 +1852,630 @@
}
/**
- * Final callback from terminating worker. Removes record of
- * worker from array, and adjusts counts. If pool is shutting
- * down, tries to complete termination.
+ * Tries to locate and execute tasks for a stealer of the given
+ * task, or in turn one of its stealers, Traces currentSteal ->
+ * currentJoin links looking for a thread working on a descendant
+ * of the given task and with a non-empty queue to steal back and
+ * execute tasks from. The first call to this method upon a
+ * waiting join will often entail scanning/search, (which is OK
+ * because the joiner has nothing better to do), but this method
+ * leaves hints in workers to speed up subsequent calls. The
+ * implementation is very branchy to cope with potential
+ * inconsistencies or loops encountering chains that are stale,
+ * unknown, or so long that they are likely cyclic.
*
- * @param w the worker
+ * @param joiner the joining worker
+ * @param task the task to join
+ * @return 0 if no progress can be made, negative if task
+ * known complete, else positive
*/
- final void deregisterWorker(ForkJoinWorkerThread w, Throwable ex) {
- int idx = w.poolIndex;
- int sc = w.stealCount;
- int steps = 0;
- // Remove from array, adjust worker counts and collect steal count.
- // We can intermix failed removes or adjusts with steal updates
- do {
- long s, c;
- int g;
- if (steps == 0 && ((g = scanGuard) & SG_UNIT) == 0 &&
- UNSAFE.compareAndSwapInt(this, scanGuardOffset,
- g, g |= SG_UNIT)) {
- ForkJoinWorkerThread[] ws = workers;
- if (ws != null && idx >= 0 &&
- idx < ws.length && ws[idx] == w)
- ws[idx] = null; // verify
- nextWorkerIndex = idx;
- scanGuard = g + SG_UNIT;
- steps = 1;
- }
- if (steps == 1 &&
- UNSAFE.compareAndSwapLong(this, ctlOffset, c = ctl,
- (((c - AC_UNIT) & AC_MASK) |
- ((c - TC_UNIT) & TC_MASK) |
- (c & ~(AC_MASK|TC_MASK)))))
- steps = 2;
- if (sc != 0 &&
- UNSAFE.compareAndSwapLong(this, stealCountOffset,
- s = stealCount, s + sc))
- sc = 0;
- } while (steps != 2 || sc != 0);
- if (!tryTerminate(false)) {
- if (ex != null) // possibly replace if died abnormally
- signalWork();
- else
- tryReleaseWaiter();
- }
- }
-
- // Shutdown and termination
-
- /**
- * Possibly initiates and/or completes termination.
- *
- * @param now if true, unconditionally terminate, else only
- * if shutdown and empty queue and no active workers
- * @return true if now terminating or terminated
- */
- private boolean tryTerminate(boolean now) {
- long c;
- while (((c = ctl) & STOP_BIT) == 0) {
- if (!now) {
- if ((int)(c >> AC_SHIFT) != -parallelism)
- return false;
- if (!shutdown || blockedCount != 0 || quiescerCount != 0 ||
- queueBase != queueTop) {
- if (ctl == c) // staleness check
- return false;
- continue;
- }
- }
- if (UNSAFE.compareAndSwapLong(this, ctlOffset, c, c | STOP_BIT))
- startTerminating();
- }
- if ((short)(c >>> TC_SHIFT) == -parallelism) { // signal when 0 workers
- final ReentrantLock lock = this.submissionLock;
- lock.lock();
- try {
- termination.signalAll();
- } finally {
- lock.unlock();
- }
- }
- return true;
- }
-
- /**
- * Runs up to three passes through workers: (0) Setting
- * termination status for each worker, followed by wakeups up to
- * queued workers; (1) helping cancel tasks; (2) interrupting
- * lagging threads (likely in external tasks, but possibly also
- * blocked in joins). Each pass repeats previous steps because of
- * potential lagging thread creation.
- */
- private void startTerminating() {
- cancelSubmissions();
- for (int pass = 0; pass < 3; ++pass) {
- ForkJoinWorkerThread[] ws = workers;
- if (ws != null) {
- for (ForkJoinWorkerThread w : ws) {
- if (w != null) {
- w.terminate = true;
- if (pass > 0) {
- w.cancelTasks();
- if (pass > 1 && !w.isInterrupted()) {
- try {
- w.interrupt();
- } catch (SecurityException ignore) {
- }
+ private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
+ int stat = 0, steps = 0; // bound to avoid cycles
+ if (joiner != null && task != null) { // hoist null checks
+ restart: for (;;) {
+ ForkJoinTask<?> subtask = task; // current target
+ for (WorkQueue j = joiner, v;;) { // v is stealer of subtask
+ WorkQueue[] ws; int m, s, h;
+ if ((s = task.status) < 0) {
+ stat = s;
+ break restart;
+ }
+ if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
+ break restart; // shutting down
+ if ((v = ws[h = (j.hint | 1) & m]) == null ||
+ v.currentSteal != subtask) {
+ for (int origin = h;;) { // find stealer
+ if (((h = (h + 2) & m) & 15) == 1 &&
+ (subtask.status < 0 || j.currentJoin != subtask))
+ continue restart; // occasional staleness check
+ if ((v = ws[h]) != null &&
+ v.currentSteal == subtask) {
+ j.hint = h; // save hint
+ break;
+ }
+ if (h == origin)
+ break restart; // cannot find stealer
+ }
+ }
+ for (;;) { // help stealer or descend to its stealer
+ ForkJoinTask[] a; int b;
+ if (subtask.status < 0) // surround probes with
+ continue restart; // consistency checks
+ if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
+ int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ ForkJoinTask<?> t =
+ (ForkJoinTask<?>)U.getObjectVolatile(a, i);
+ if (subtask.status < 0 || j.currentJoin != subtask ||
+ v.currentSteal != subtask)
+ continue restart; // stale
+ stat = 1; // apparent progress
+ if (t != null && v.base == b &&
+ U.compareAndSwapObject(a, i, t, null)) {
+ v.base = b + 1; // help stealer
+ joiner.runSubtask(t);
+ }
+ else if (v.base == b && ++steps == MAX_HELP)
+ break restart; // v apparently stalled
+ }
+ else { // empty -- try to descend
+ ForkJoinTask<?> next = v.currentJoin;
+ if (subtask.status < 0 || j.currentJoin != subtask ||
+ v.currentSteal != subtask)
+ continue restart; // stale
+ else if (next == null || ++steps == MAX_HELP)
+ break restart; // dead-end or maybe cyclic
+ else {
+ subtask = next;
+ j = v;
+ break;
}
}
}
}
- terminateWaiters();
}
}
+ return stat;
+ }
+
+ /**
+ * Analog of tryHelpStealer for CountedCompleters. Tries to steal
+ * and run tasks within the target's computation.
+ *
+ * @param task the task to join
+ * @param mode if shared, exit upon completing any task
+ * if all workers are active
+ */
+ private int helpComplete(ForkJoinTask<?> task, int mode) {
+ WorkQueue[] ws; WorkQueue q; int m, n, s, u;
+ if (task != null && (ws = workQueues) != null &&
+ (m = ws.length - 1) >= 0) {
+ for (int j = 1, origin = j;;) {
+ if ((s = task.status) < 0)
+ return s;
+ if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) {
+ origin = j;
+ if (mode == SHARED_QUEUE &&
+ ((u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0))
+ break;
+ }
+ else if ((j = (j + 2) & m) == origin)
+ break;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * Tries to decrement active count (sometimes implicitly) and
+ * possibly release or create a compensating worker in preparation
+ * for blocking. Fails on contention or termination. Otherwise,
+ * adds a new thread if no idle workers are available and pool
+ * may become starved.
+ */
+ final boolean tryCompensate() {
+ int pc = config & SMASK, e, i, tc; long c;
+ WorkQueue[] ws; WorkQueue w; Thread p;
+ if ((ws = workQueues) != null && (e = (int)(c = ctl)) >= 0) {
+ if (e != 0 && (i = e & SMASK) < ws.length &&
+ (w = ws[i]) != null && w.eventCount == (e | INT_SIGN)) {
+ long nc = ((long)(w.nextWait & E_MASK) |
+ (c & (AC_MASK|TC_MASK)));
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ w.eventCount = (e + E_SEQ) & E_MASK;
+ if ((p = w.parker) != null)
+ U.unpark(p);
+ return true; // replace with idle worker
+ }
+ }
+ else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 &&
+ (int)(c >> AC_SHIFT) + pc > 1) {
+ long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK);
+ if (U.compareAndSwapLong(this, CTL, c, nc))
+ return true; // no compensation
+ }
+ else if (tc + pc < MAX_CAP) {
+ long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK);
+ if (U.compareAndSwapLong(this, CTL, c, nc)) {
+ ForkJoinWorkerThreadFactory fac;
+ Throwable ex = null;
+ ForkJoinWorkerThread wt = null;
+ try {
+ if ((fac = factory) != null &&
+ (wt = fac.newThread(this)) != null) {
+ wt.start();
+ return true;
+ }
+ } catch (Throwable rex) {
+ ex = rex;
+ }
+ deregisterWorker(wt, ex); // clean up and return false
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Helps and/or blocks until the given task is done.
+ *
+ * @param joiner the joining worker
+ * @param task the task
+ * @return task status on exit
+ */
+ final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
+ int s = 0;
+ if (joiner != null && task != null && (s = task.status) >= 0) {
+ ForkJoinTask<?> prevJoin = joiner.currentJoin;
+ joiner.currentJoin = task;
+ do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
+ joiner.tryRemoveAndExec(task)); // process local tasks
+ if (s >= 0 && (s = task.status) >= 0) {
+ helpSignal(task, joiner.poolIndex);
+ if ((s = task.status) >= 0 &&
+ (task instanceof CountedCompleter))
+ s = helpComplete(task, LIFO_QUEUE);
+ }
+ while (s >= 0 && (s = task.status) >= 0) {
+ if ((!joiner.isEmpty() || // try helping
+ (s = tryHelpStealer(joiner, task)) == 0) &&
+ (s = task.status) >= 0) {
+ helpSignal(task, joiner.poolIndex);
+ if ((s = task.status) >= 0 && tryCompensate()) {
+ if (task.trySetSignal() && (s = task.status) >= 0) {
+ synchronized (task) {
+ if (task.status >= 0) {
+ try { // see ForkJoinTask
+ task.wait(); // for explanation
+ } catch (InterruptedException ie) {
+ }
+ }
+ else
+ task.notifyAll();
+ }
+ }
+ long c; // re-activate
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, c + AC_UNIT));
+ }
+ }
+ }
+ joiner.currentJoin = prevJoin;
+ }
+ return s;
+ }
+
+ /**
+ * Stripped-down variant of awaitJoin used by timed joins. Tries
+ * to help join only while there is continuous progress. (Caller
+ * will then enter a timed wait.)
+ *
+ * @param joiner the joining worker
+ * @param task the task
+ */
+ final void helpJoinOnce(WorkQueue joiner, ForkJoinTask<?> task) {
+ int s;
+ if (joiner != null && task != null && (s = task.status) >= 0) {
+ ForkJoinTask<?> prevJoin = joiner.currentJoin;
+ joiner.currentJoin = task;
+ do {} while ((s = task.status) >= 0 && !joiner.isEmpty() &&
+ joiner.tryRemoveAndExec(task));
+ if (s >= 0 && (s = task.status) >= 0) {
+ helpSignal(task, joiner.poolIndex);
+ if ((s = task.status) >= 0 &&
+ (task instanceof CountedCompleter))
+ s = helpComplete(task, LIFO_QUEUE);
+ }
+ if (s >= 0 && joiner.isEmpty()) {
+ do {} while (task.status >= 0 &&
+ tryHelpStealer(joiner, task) > 0);
+ }
+ joiner.currentJoin = prevJoin;
+ }
}
/**
- * Polls and cancels all submissions. Called only during termination.
+ * Returns a (probably) non-empty steal queue, if one is found
+ * during a random, then cyclic scan, else null. This method must
+ * be retried by caller if, by the time it tries to use the queue,
+ * it is empty.
+ * @param r a (random) seed for scanning
*/
- private void cancelSubmissions() {
- while (queueBase != queueTop) {
- ForkJoinTask<?> task = pollSubmission();
- if (task != null) {
- try {
- task.cancel(false);
- } catch (Throwable ignore) {
+ private WorkQueue findNonEmptyStealQueue(int r) {
+ for (WorkQueue[] ws;;) {
+ int ps = plock, m, n;
+ if ((ws = workQueues) == null || (m = ws.length - 1) < 1)
+ return null;
+ for (int j = (m + 1) << 2; ;) {
+ WorkQueue q = ws[(((r + j) << 1) | 1) & m];
+ if (q != null && (n = q.base - q.top) < 0) {
+ if (n < -1)
+ signalWork(q);
+ return q;
+ }
+ else if (--j < 0) {
+ if (plock == ps)
+ return null;
+ break;
}
}
}
}
/**
- * Tries to set the termination status of waiting workers, and
- * then wakes them up (after which they will terminate).
+ * Runs tasks until {@code isQuiescent()}. We piggyback on
+ * active count ctl maintenance, but rather than blocking
+ * when tasks cannot be found, we rescan until all others cannot
+ * find tasks either.
*/
- private void terminateWaiters() {
- ForkJoinWorkerThread[] ws = workers;
- if (ws != null) {
- ForkJoinWorkerThread w; long c; int i, e;
- int n = ws.length;
- while ((i = ~(e = (int)(c = ctl)) & SMASK) < n &&
- (w = ws[i]) != null && w.eventCount == (e & E_MASK)) {
- if (UNSAFE.compareAndSwapLong(this, ctlOffset, c,
- (long)(w.nextWait & E_MASK) |
- ((c + AC_UNIT) & AC_MASK) |
- (c & (TC_MASK|STOP_BIT)))) {
- w.terminate = true;
- w.eventCount = e + EC_UNIT;
- if (w.parked)
- UNSAFE.unpark(w);
+ final void helpQuiescePool(WorkQueue w) {
+ for (boolean active = true;;) {
+ ForkJoinTask<?> localTask; // exhaust local queue
+ while ((localTask = w.nextLocalTask()) != null)
+ localTask.doExec();
+ // Similar to loop in scan(), but ignoring submissions
+ WorkQueue q = findNonEmptyStealQueue(w.nextSeed());
+ if (q != null) {
+ ForkJoinTask<?> t; int b;
+ if (!active) { // re-establish active count
+ long c;
+ active = true;
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, c + AC_UNIT));
+ }
+ if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+ w.runSubtask(t);
+ }
+ else {
+ long c;
+ if (active) { // decrement active count without queuing
+ active = false;
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, c -= AC_UNIT));
+ }
+ else
+ c = ctl; // re-increment on exit
+ if ((int)(c >> AC_SHIFT) + (config & SMASK) == 0) {
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, c + AC_UNIT));
+ break;
}
}
}
}
- // misc ForkJoinWorkerThread support
-
/**
- * Increments or decrements quiescerCount. Needed only to prevent
- * triggering shutdown if a worker is transiently inactive while
- * checking quiescence.
+ * Gets and removes a local or stolen task for the given worker.
*
- * @param delta 1 for increment, -1 for decrement
+ * @return a task, if available
*/
- final void addQuiescerCount(int delta) {
- int c;
- do {} while (!UNSAFE.compareAndSwapInt(this, quiescerCountOffset,
- c = quiescerCount, c + delta));
+ final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
+ for (ForkJoinTask<?> t;;) {
+ WorkQueue q; int b;
+ if ((t = w.nextLocalTask()) != null)
+ return t;
+ if ((q = findNonEmptyStealQueue(w.nextSeed())) == null)
+ return null;
+ if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null)
+ return t;
+ }
}
/**
- * Directly increments or decrements active count without queuing.
- * This method is used to transiently assert inactivation while
- * checking quiescence.
+ * Returns a cheap heuristic guide for task partitioning when
+ * programmers, frameworks, tools, or languages have little or no
+ * idea about task granularity. In essence by offering this
+ * method, we ask users only about tradeoffs in overhead vs
+ * expected throughput and its variance, rather than how finely to
+ * partition tasks.
*
- * @param delta 1 for increment, -1 for decrement
+ * In a steady state strict (tree-structured) computation, each
+ * thread makes available for stealing enough tasks for other
+ * threads to remain active. Inductively, if all threads play by
+ * the same rules, each thread should make available only a
+ * constant number of tasks.
+ *
+ * The minimum useful constant is just 1. But using a value of 1
+ * would require immediate replenishment upon each steal to
+ * maintain enough tasks, which is infeasible. Further,
+ * partitionings/granularities of offered tasks should minimize
+ * steal rates, which in general means that threads nearer the top
+ * of computation tree should generate more than those nearer the
+ * bottom. In perfect steady state, each thread is at
+ * approximately the same level of computation tree. However,
+ * producing extra tasks amortizes the uncertainty of progress and
+ * diffusion assumptions.
+ *
+ * So, users will want to use values larger (but not much larger)
+ * than 1 to both smooth over transient shortages and hedge
+ * against uneven progress; as traded off against the cost of
+ * extra task overhead. We leave the user to pick a threshold
+ * value to compare with the results of this call to guide
+ * decisions, but recommend values such as 3.
+ *
+ * When all threads are active, it is on average OK to estimate
+ * surplus strictly locally. In steady-state, if one thread is
+ * maintaining say 2 surplus tasks, then so are others. So we can
+ * just use estimated queue length. However, this strategy alone
+ * leads to serious mis-estimates in some non-steady-state
+ * conditions (ramp-up, ramp-down, other stalls). We can detect
+ * many of these by further considering the number of "idle"
+ * threads, that are known to have zero queued tasks, so
+ * compensate by a factor of (#idle/#active) threads.
+ *
+ * Note: The approximation of #busy workers as #active workers is
+ * not very good under current signalling scheme, and should be
+ * improved.
*/
- final void addActiveCount(int delta) {
- long d = (long)delta << AC_SHIFT;
- long c;
- do {} while (!UNSAFE.compareAndSwapLong(this, ctlOffset,
- c = ctl, c + d));
+ static int getSurplusQueuedTaskCount() {
+ Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
+ if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) {
+ int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
+ int n = (q = wt.workQueue).top - q.base;
+ int a = (int)(pool.ctl >> AC_SHIFT) + p;
+ return n - (a > (p >>>= 1) ? 0 :
+ a > (p >>>= 1) ? 1 :
+ a > (p >>>= 1) ? 2 :
+ a > (p >>>= 1) ? 4 :
+ 8);
+ }
+ return 0;
+ }
+
+ // Termination
+
+ /**
+ * Possibly initiates and/or completes termination. The caller
+ * triggering termination runs three passes through workQueues:
+ * (0) Setting termination status, followed by wakeups of queued
+ * workers; (1) cancelling all tasks; (2) interrupting lagging
+ * threads (likely in external tasks, but possibly also blocked in
+ * joins). Each pass repeats previous steps because of potential
+ * lagging thread creation.
+ *
+ * @param now if true, unconditionally terminate, else only
+ * if no work and no active workers
+ * @param enable if true, enable shutdown when next possible
+ * @return true if now terminating or terminated
+ */
+ private boolean tryTerminate(boolean now, boolean enable) {
+ if (this == commonPool) // cannot shut down
+ return false;
+ for (long c;;) {
+ if (((c = ctl) & STOP_BIT) != 0) { // already terminating
+ if ((short)(c >>> TC_SHIFT) == -(config & SMASK)) {
+ synchronized (this) {
+ notifyAll(); // signal when 0 workers
+ }
+ }
+ return true;
+ }
+ if (plock >= 0) { // not yet enabled
+ int ps;
+ if (!enable)
+ return false;
+ if (((ps = plock) & PL_LOCK) != 0 ||
+ !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK))
+ ps = acquirePlock();
+ if (!U.compareAndSwapInt(this, PLOCK, ps, SHUTDOWN))
+ releasePlock(SHUTDOWN);
+ }
+ if (!now) { // check if idle & no tasks
+ if ((int)(c >> AC_SHIFT) != -(config & SMASK) ||
+ hasQueuedSubmissions())
+ return false;
+ // Check for unqueued inactive workers. One pass suffices.
+ WorkQueue[] ws = workQueues; WorkQueue w;
+ if (ws != null) {
+ for (int i = 1; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null && w.eventCount >= 0)
+ return false;
+ }
+ }
+ }
+ if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) {
+ for (int pass = 0; pass < 3; ++pass) {
+ WorkQueue[] ws = workQueues;
+ if (ws != null) {
+ WorkQueue w; Thread wt;
+ int n = ws.length;
+ for (int i = 0; i < n; ++i) {
+ if ((w = ws[i]) != null) {
+ w.qlock = -1;
+ if (pass > 0) {
+ w.cancelAll();
+ if (pass > 1 && (wt = w.owner) != null) {
+ if (!wt.isInterrupted()) {
+ try {
+ wt.interrupt();
+ } catch (SecurityException ignore) {
+ }
+ }
+ U.unpark(wt);
+ }
+ }
+ }
+ }
+ // Wake up workers parked on event queue
+ int i, e; long cc; Thread p;
+ while ((e = (int)(cc = ctl) & E_MASK) != 0 &&
+ (i = e & SMASK) < n &&
+ (w = ws[i]) != null) {
+ long nc = ((long)(w.nextWait & E_MASK) |
+ ((cc + AC_UNIT) & AC_MASK) |
+ (cc & (TC_MASK|STOP_BIT)));
+ if (w.eventCount == (e | INT_SIGN) &&
+ U.compareAndSwapLong(this, CTL, cc, nc)) {
+ w.eventCount = (e + E_SEQ) & E_MASK;
+ w.qlock = -1;
+ if ((p = w.parker) != null)
+ U.unpark(p);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // external operations on common pool
+
+ /**
+ * Returns common pool queue for a thread that has submitted at
+ * least one task.
+ */
+ static WorkQueue commonSubmitterQueue() {
+ ForkJoinPool p; WorkQueue[] ws; int m; Submitter z;
+ return ((z = submitters.get()) != null &&
+ (p = commonPool) != null &&
+ (ws = p.workQueues) != null &&
+ (m = ws.length - 1) >= 0) ?
+ ws[m & z.seed & SQMASK] : null;
}
/**
- * Returns the approximate (non-atomic) number of idle threads per
- * active thread.
+ * Tries to pop the given task from submitter's queue in common pool.
*/
- final int idlePerActive() {
- // Approximate at powers of two for small values, saturate past 4
- int p = parallelism;
- int a = p + (int)(ctl >> AC_SHIFT);
- return (a > (p >>>= 1) ? 0 :
- a > (p >>>= 1) ? 1 :
- a > (p >>>= 1) ? 2 :
- a > (p >>>= 1) ? 4 :
- 8);
+ static boolean tryExternalUnpush(ForkJoinTask<?> t) {
+ ForkJoinPool p; WorkQueue[] ws; WorkQueue q; Submitter z;
+ ForkJoinTask<?>[] a; int m, s;
+ if (t != null &&
+ (z = submitters.get()) != null &&
+ (p = commonPool) != null &&
+ (ws = p.workQueues) != null &&
+ (m = ws.length - 1) >= 0 &&
+ (q = ws[m & z.seed & SQMASK]) != null &&
+ (s = q.top) != q.base &&
+ (a = q.array) != null) {
+ long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE;
+ if (U.getObject(a, j) == t &&
+ U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+ if (q.array == a && q.top == s && // recheck
+ U.compareAndSwapObject(a, j, t, null)) {
+ q.top = s - 1;
+ q.qlock = 0;
+ return true;
+ }
+ q.qlock = 0;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tries to pop and run local tasks within the same computation
+ * as the given root. On failure, tries to help complete from
+ * other queues via helpComplete.
+ */
+ private void externalHelpComplete(WorkQueue q, ForkJoinTask<?> root) {
+ ForkJoinTask<?>[] a; int m;
+ if (q != null && (a = q.array) != null && (m = (a.length - 1)) >= 0 &&
+ root != null && root.status >= 0) {
+ for (;;) {
+ int s, u; Object o; CountedCompleter<?> task = null;
+ if ((s = q.top) - q.base > 0) {
+ long j = ((m & (s - 1)) << ASHIFT) + ABASE;
+ if ((o = U.getObject(a, j)) != null &&
+ (o instanceof CountedCompleter)) {
+ CountedCompleter<?> t = (CountedCompleter<?>)o, r = t;
+ do {
+ if (r == root) {
+ if (U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+ if (q.array == a && q.top == s &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ q.top = s - 1;
+ task = t;
+ }
+ q.qlock = 0;
+ }
+ break;
+ }
+ } while ((r = r.completer) != null);
+ }
+ }
+ if (task != null)
+ task.doExec();
+ if (root.status < 0 ||
+ (u = (int)(ctl >>> 32)) >= 0 || (u >> UAC_SHIFT) >= 0)
+ break;
+ if (task == null) {
+ helpSignal(root, q.poolIndex);
+ if (root.status >= 0)
+ helpComplete(root, SHARED_QUEUE);
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Tries to help execute or signal availability of the given task
+ * from submitter's queue in common pool.
+ */
+ static void externalHelpJoin(ForkJoinTask<?> t) {
+ // Some hard-to-avoid overlap with tryExternalUnpush
+ ForkJoinPool p; WorkQueue[] ws; WorkQueue q, w; Submitter z;
+ ForkJoinTask<?>[] a; int m, s, n;
+ if (t != null &&
+ (z = submitters.get()) != null &&
+ (p = commonPool) != null &&
+ (ws = p.workQueues) != null &&
+ (m = ws.length - 1) >= 0 &&
+ (q = ws[m & z.seed & SQMASK]) != null &&
+ (a = q.array) != null) {
+ int am = a.length - 1;
+ if ((s = q.top) != q.base) {
+ long j = ((am & (s - 1)) << ASHIFT) + ABASE;
+ if (U.getObject(a, j) == t &&
+ U.compareAndSwapInt(q, QLOCK, 0, 1)) {
+ if (q.array == a && q.top == s &&
+ U.compareAndSwapObject(a, j, t, null)) {
+ q.top = s - 1;
+ q.qlock = 0;
+ t.doExec();
+ }
+ else
+ q.qlock = 0;
+ }
+ }
+ if (t.status >= 0) {
+ if (t instanceof CountedCompleter)
+ p.externalHelpComplete(q, t);
+ else
+ p.helpSignal(t, q.poolIndex);
+ }
+ }
+ }
+
+ /**
+ * Restricted version of helpQuiescePool for external callers
+ */
+ static void externalHelpQuiescePool() {
+ ForkJoinPool p; ForkJoinTask<?> t; WorkQueue q; int b;
+ if ((p = commonPool) != null &&
+ (q = p.findNonEmptyStealQueue(1)) != null &&
+ (b = q.base) - q.top < 0 &&
+ (t = q.pollAt(b)) != null)
+ t.doExec();
}
// Exported methods
@@ -1379,7 +2489,7 @@
* no UncaughtExceptionHandler, and non-async LIFO processing mode.
*/
public ForkJoinPool() {
- this(Runtime.getRuntime().availableProcessors(),
+ this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
defaultForkJoinWorkerThreadFactory, null, false);
}
@@ -1424,31 +2534,46 @@
checkPermission();
if (factory == null)
throw new NullPointerException();
- if (parallelism <= 0 || parallelism > MAX_ID)
+ if (parallelism <= 0 || parallelism > MAX_CAP)
throw new IllegalArgumentException();
- this.parallelism = parallelism;
this.factory = factory;
this.ueh = handler;
- this.locallyFifo = asyncMode;
+ this.config = parallelism | (asyncMode ? (FIFO_QUEUE << 16) : 0);
long np = (long)(-parallelism); // offset ctl counts
this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
- this.submissionQueue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
- // initialize workers array with room for 2*parallelism if possible
- int n = parallelism << 1;
- if (n >= MAX_ID)
- n = MAX_ID;
- else { // See Hackers Delight, sec 3.2, where n < (1 << 16)
- n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8;
- }
- workers = new ForkJoinWorkerThread[n + 1];
- this.submissionLock = new ReentrantLock();
- this.termination = submissionLock.newCondition();
+ int pn = nextPoolId();
StringBuilder sb = new StringBuilder("ForkJoinPool-");
- sb.append(poolNumberGenerator.incrementAndGet());
+ sb.append(Integer.toString(pn));
sb.append("-worker-");
this.workerNamePrefix = sb.toString();
}
+ /**
+ * Constructor for common pool, suitable only for static initialization.
+ * Basically the same as above, but uses smallest possible initial footprint.
+ */
+ ForkJoinPool(int parallelism, long ctl,
+ ForkJoinWorkerThreadFactory factory,
+ Thread.UncaughtExceptionHandler handler) {
+ this.config = parallelism;
+ this.ctl = ctl;
+ this.factory = factory;
+ this.ueh = handler;
+ this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+ }
+
+ /**
+ * Returns the common pool instance.
+ *
+ * @return the common pool instance
+ * @since 1.8
+ * @hide
+ */
+ public static ForkJoinPool commonPool() {
+ // assert commonPool != null : "static init error";
+ return commonPool;
+ }
+
// Execution methods
/**
@@ -1468,34 +2593,10 @@
* scheduled for execution
*/
public <T> T invoke(ForkJoinTask<T> task) {
- Thread t = Thread.currentThread();
if (task == null)
throw new NullPointerException();
- if (shutdown)
- throw new RejectedExecutionException();
- if ((t instanceof ForkJoinWorkerThread) &&
- ((ForkJoinWorkerThread)t).pool == this)
- return task.invoke(); // bypass submit if in same pool
- else {
- addSubmission(task);
- return task.join();
- }
- }
-
- /**
- * Unless terminating, forks task if within an ongoing FJ
- * computation in the current pool, else submits as external task.
- */
- private <T> void forkOrSubmit(ForkJoinTask<T> task) {
- ForkJoinWorkerThread w;
- Thread t = Thread.currentThread();
- if (shutdown)
- throw new RejectedExecutionException();
- if ((t instanceof ForkJoinWorkerThread) &&
- (w = (ForkJoinWorkerThread)t).pool == this)
- w.pushTask(task);
- else
- addSubmission(task);
+ externalPush(task);
+ return task.join();
}
/**
@@ -1509,7 +2610,7 @@
public void execute(ForkJoinTask<?> task) {
if (task == null)
throw new NullPointerException();
- forkOrSubmit(task);
+ externalPush(task);
}
// AbstractExecutorService methods
@@ -1526,8 +2627,8 @@
if (task instanceof ForkJoinTask<?>) // avoid re-wrap
job = (ForkJoinTask<?>) task;
else
- job = ForkJoinTask.adapt(task, null);
- forkOrSubmit(job);
+ job = new ForkJoinTask.AdaptedRunnableAction(task);
+ externalPush(job);
}
/**
@@ -1542,7 +2643,7 @@
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) {
if (task == null)
throw new NullPointerException();
- forkOrSubmit(task);
+ externalPush(task);
return task;
}
@@ -1552,10 +2653,8 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Callable<T> task) {
- if (task == null)
- throw new NullPointerException();
- ForkJoinTask<T> job = ForkJoinTask.adapt(task);
- forkOrSubmit(job);
+ ForkJoinTask<T> job = new ForkJoinTask.AdaptedCallable<T>(task);
+ externalPush(job);
return job;
}
@@ -1565,10 +2664,8 @@
* scheduled for execution
*/
public <T> ForkJoinTask<T> submit(Runnable task, T result) {
- if (task == null)
- throw new NullPointerException();
- ForkJoinTask<T> job = ForkJoinTask.adapt(task, result);
- forkOrSubmit(job);
+ ForkJoinTask<T> job = new ForkJoinTask.AdaptedRunnable<T>(task, result);
+ externalPush(job);
return job;
}
@@ -1584,8 +2681,8 @@
if (task instanceof ForkJoinTask<?>) // avoid re-wrap
job = (ForkJoinTask<?>) task;
else
- job = ForkJoinTask.adapt(task, null);
- forkOrSubmit(job);
+ job = new ForkJoinTask.AdaptedRunnableAction(task);
+ externalPush(job);
return job;
}
@@ -1594,25 +2691,27 @@
* @throws RejectedExecutionException {@inheritDoc}
*/
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) {
- ArrayList<ForkJoinTask<T>> forkJoinTasks =
- new ArrayList<ForkJoinTask<T>>(tasks.size());
- for (Callable<T> task : tasks)
- forkJoinTasks.add(ForkJoinTask.adapt(task));
- invoke(new InvokeAll<T>(forkJoinTasks));
+ // In previous versions of this class, this method constructed
+ // a task to run ForkJoinTask.invokeAll, but now external
+ // invocation of multiple tasks is at least as efficient.
+ ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
- @SuppressWarnings({"unchecked", "rawtypes"})
- List<Future<T>> futures = (List<Future<T>>) (List) forkJoinTasks;
- return futures;
- }
-
- static final class InvokeAll<T> extends RecursiveAction {
- final ArrayList<ForkJoinTask<T>> tasks;
- InvokeAll(ArrayList<ForkJoinTask<T>> tasks) { this.tasks = tasks; }
- public void compute() {
- try { invokeAll(tasks); }
- catch (Exception ignore) {}
+ boolean done = false;
+ try {
+ for (Callable<T> t : tasks) {
+ ForkJoinTask<T> f = new ForkJoinTask.AdaptedCallable<T>(t);
+ futures.add(f);
+ externalPush(f);
+ }
+ for (int i = 0, size = futures.size(); i < size; i++)
+ ((ForkJoinTask<?>)futures.get(i)).quietlyJoin();
+ done = true;
+ return futures;
+ } finally {
+ if (!done)
+ for (int i = 0, size = futures.size(); i < size; i++)
+ futures.get(i).cancel(false);
}
- private static final long serialVersionUID = -7914297376763021607L;
}
/**
@@ -1640,7 +2739,18 @@
* @return the targeted parallelism level of this pool
*/
public int getParallelism() {
- return parallelism;
+ return config & SMASK;
+ }
+
+ /**
+ * Returns the targeted parallelism level of the common pool.
+ *
+ * @return the targeted parallelism level of the common pool
+ * @since 1.8
+ * @hide
+ */
+ public static int getCommonPoolParallelism() {
+ return commonPoolParallelism;
}
/**
@@ -1652,7 +2762,7 @@
* @return the number of worker threads
*/
public int getPoolSize() {
- return parallelism + (short)(ctl >>> TC_SHIFT);
+ return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
}
/**
@@ -1662,7 +2772,7 @@
* @return {@code true} if this pool uses async mode
*/
public boolean getAsyncMode() {
- return locallyFifo;
+ return (config >>> 16) == FIFO_QUEUE;
}
/**
@@ -1674,8 +2784,15 @@
* @return the number of worker threads
*/
public int getRunningThreadCount() {
- int r = parallelism + (int)(ctl >> AC_SHIFT);
- return (r <= 0) ? 0 : r; // suppress momentarily negative values
+ int rc = 0;
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 1; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null && w.isApparentlyUnblocked())
+ ++rc;
+ }
+ }
+ return rc;
}
/**
@@ -1686,7 +2803,7 @@
* @return the number of active threads
*/
public int getActiveThreadCount() {
- int r = parallelism + (int)(ctl >> AC_SHIFT) + blockedCount;
+ int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
return (r <= 0) ? 0 : r; // suppress momentarily negative values
}
@@ -1702,7 +2819,7 @@
* @return {@code true} if all threads are currently idle
*/
public boolean isQuiescent() {
- return parallelism + (int)(ctl >> AC_SHIFT) + blockedCount == 0;
+ return (int)(ctl >> AC_SHIFT) + (config & SMASK) == 0;
}
/**
@@ -1717,7 +2834,15 @@
* @return the number of steals
*/
public long getStealCount() {
- return stealCount;
+ long count = stealCount;
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 1; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null)
+ count += w.nsteals;
+ }
+ }
+ return count;
}
/**
@@ -1732,12 +2857,12 @@
*/
public long getQueuedTaskCount() {
long count = 0;
- ForkJoinWorkerThread[] ws;
- if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
- (ws = workers) != null) {
- for (ForkJoinWorkerThread w : ws)
- if (w != null)
- count -= w.queueBase - w.queueTop; // must read base first
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 1; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null)
+ count += w.queueSize();
+ }
}
return count;
}
@@ -1750,7 +2875,15 @@
* @return the number of queued submissions
*/
public int getQueuedSubmissionCount() {
- return -queueBase + queueTop;
+ int count = 0;
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null)
+ count += w.queueSize();
+ }
+ }
+ return count;
}
/**
@@ -1760,7 +2893,14 @@
* @return {@code true} if there are any queued submissions
*/
public boolean hasQueuedSubmissions() {
- return queueBase != queueTop;
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null && !w.isEmpty())
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -1771,16 +2911,11 @@
* @return the next submission, or {@code null} if none
*/
protected ForkJoinTask<?> pollSubmission() {
- ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
- while ((b = queueBase) != queueTop &&
- (q = submissionQueue) != null &&
- (i = (q.length - 1) & b) >= 0) {
- long u = (i << ASHIFT) + ABASE;
- if ((t = q[i]) != null &&
- queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- queueBase = b + 1;
- return t;
+ WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; i += 2) {
+ if ((w = ws[i]) != null && (t = w.poll()) != null)
+ return t;
}
}
return null;
@@ -1805,20 +2940,17 @@
*/
protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
int count = 0;
- while (queueBase != queueTop) {
- ForkJoinTask<?> t = pollSubmission();
- if (t != null) {
- c.add(t);
- ++count;
+ WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; ++i) {
+ if ((w = ws[i]) != null) {
+ while ((t = w.poll()) != null) {
+ c.add(t);
+ ++count;
+ }
+ }
}
}
- ForkJoinWorkerThread[] ws;
- if ((short)(ctl >>> TC_SHIFT) > -parallelism &&
- (ws = workers) != null) {
- for (ForkJoinWorkerThread w : ws)
- if (w != null)
- count += w.drainTasksTo(c);
- }
return count;
}
@@ -1830,21 +2962,36 @@
* @return a string identifying this pool, as well as its state
*/
public String toString() {
- long st = getStealCount();
- long qt = getQueuedTaskCount();
- long qs = getQueuedSubmissionCount();
- int pc = parallelism;
+ // Use a single pass through workQueues to collect counts
+ long qt = 0L, qs = 0L; int rc = 0;
+ long st = stealCount;
long c = ctl;
+ WorkQueue[] ws; WorkQueue w;
+ if ((ws = workQueues) != null) {
+ for (int i = 0; i < ws.length; ++i) {
+ if ((w = ws[i]) != null) {
+ int size = w.queueSize();
+ if ((i & 1) == 0)
+ qs += size;
+ else {
+ qt += size;
+ st += w.nsteals;
+ if (w.isApparentlyUnblocked())
+ ++rc;
+ }
+ }
+ }
+ }
+ int pc = (config & SMASK);
int tc = pc + (short)(c >>> TC_SHIFT);
- int rc = pc + (int)(c >> AC_SHIFT);
- if (rc < 0) // ignore transient negative
- rc = 0;
- int ac = rc + blockedCount;
+ int ac = pc + (int)(c >> AC_SHIFT);
+ if (ac < 0) // ignore transient negative
+ ac = 0;
String level;
if ((c & STOP_BIT) != 0)
level = (tc == 0) ? "Terminated" : "Terminating";
else
- level = shutdown ? "Shutting down" : "Running";
+ level = plock < 0 ? "Shutting down" : "Running";
return super.toString() +
"[" + level +
", parallelism = " + pc +
@@ -1858,34 +3005,41 @@
}
/**
- * Initiates an orderly shutdown in which previously submitted
- * tasks are executed, but no new tasks will be accepted.
- * Invocation has no additional effect if already shut down.
- * Tasks that are in the process of being submitted concurrently
- * during the course of this method may or may not be rejected.
+ * Possibly initiates an orderly shutdown in which previously
+ * submitted tasks are executed, but no new tasks will be
+ * accepted. Invocation has no effect on execution state if this
+ * is the {@link #commonPool()}, and no additional effect if
+ * already shut down. Tasks that are in the process of being
+ * submitted concurrently during the course of this method may or
+ * may not be rejected.
+ *
+ * @throws SecurityException if a security manager exists and
+ * the caller is not permitted to modify threads
+ * because it does not hold {@link
+ * java.lang.RuntimePermission}{@code ("modifyThread")}
*/
public void shutdown() {
checkPermission();
- shutdown = true;
- tryTerminate(false);
+ tryTerminate(false, true);
}
/**
- * Attempts to cancel and/or stop all tasks, and reject all
- * subsequently submitted tasks. Tasks that are in the process of
- * being submitted or executed concurrently during the course of
- * this method may or may not be rejected. This method cancels
- * both existing and unexecuted tasks, in order to permit
- * termination in the presence of task dependencies. So the method
- * always returns an empty list (unlike the case for some other
- * Executors).
+ * Possibly attempts to cancel and/or stop all tasks, and reject
+ * all subsequently submitted tasks. Invocation has no effect on
+ * execution state if this is the {@link #commonPool()}, and no
+ * additional effect if already shut down. Otherwise, tasks that
+ * are in the process of being submitted or executed concurrently
+ * during the course of this method may or may not be
+ * rejected. This method cancels both existing and unexecuted
+ * tasks, in order to permit termination in the presence of task
+ * dependencies. So the method always returns an empty list
+ * (unlike the case for some other Executors).
*
* @return an empty list
*/
public List<Runnable> shutdownNow() {
checkPermission();
- shutdown = true;
- tryTerminate(true);
+ tryTerminate(true, true);
return Collections.emptyList();
}
@@ -1897,7 +3051,7 @@
public boolean isTerminated() {
long c = ctl;
return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) == -parallelism);
+ (short)(c >>> TC_SHIFT) == -(config & SMASK));
}
/**
@@ -1905,7 +3059,7 @@
* commenced but not yet completed. This method may be useful for
* debugging. A return of {@code true} reported a sufficient
* period after shutdown may indicate that submitted tasks have
- * ignored or suppressed interruption, or are waiting for IO,
+ * ignored or suppressed interruption, or are waiting for I/O,
* causing this executor not to properly terminate. (See the
* advisory notes for class {@link ForkJoinTask} stating that
* tasks should not normally entail blocking operations. But if
@@ -1916,14 +3070,7 @@
public boolean isTerminating() {
long c = ctl;
return ((c & STOP_BIT) != 0L &&
- (short)(c >>> TC_SHIFT) != -parallelism);
- }
-
- /**
- * Returns true if terminating or terminated. Used by ForkJoinWorkerThread.
- */
- final boolean isAtLeastTerminating() {
- return (ctl & STOP_BIT) != 0L;
+ (short)(c >>> TC_SHIFT) != -(config & SMASK));
}
/**
@@ -1932,13 +3079,15 @@
* @return {@code true} if this pool has been shut down
*/
public boolean isShutdown() {
- return shutdown;
+ return plock < 0;
}
/**
- * Blocks until all tasks have completed execution after a shutdown
- * request, or the timeout occurs, or the current thread is
- * interrupted, whichever happens first.
+ * Blocks until all tasks have completed execution after a
+ * shutdown request, or the timeout occurs, or the current thread
+ * is interrupted, whichever happens first. Note that the {@link
+ * #commonPool()} never terminates until program shutdown so
+ * this method will always time out.
*
* @param timeout the maximum time to wait
* @param unit the time unit of the timeout argument
@@ -1949,18 +3098,21 @@
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
- final ReentrantLock lock = this.submissionLock;
- lock.lock();
- try {
+ if (isTerminated())
+ return true;
+ if (nanos <= 0L)
+ return false;
+ long deadline = System.nanoTime() + nanos;
+ synchronized (this) {
for (;;) {
if (isTerminated())
return true;
- if (nanos <= 0)
+ if (nanos <= 0L)
return false;
- nanos = termination.awaitNanos(nanos);
+ long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+ wait(millis > 0L ? millis : 1L);
+ nanos = deadline - System.nanoTime();
}
- } finally {
- lock.unlock();
}
}
@@ -2061,11 +3213,35 @@
throws InterruptedException {
Thread t = Thread.currentThread();
if (t instanceof ForkJoinWorkerThread) {
- ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
- w.pool.awaitBlocker(blocker);
+ ForkJoinPool p = ((ForkJoinWorkerThread)t).pool;
+ while (!blocker.isReleasable()) { // variant of helpSignal
+ WorkQueue[] ws; WorkQueue q; int m, u;
+ if ((ws = p.workQueues) != null && (m = ws.length - 1) >= 0) {
+ for (int i = 0; i <= m; ++i) {
+ if (blocker.isReleasable())
+ return;
+ if ((q = ws[i]) != null && q.base - q.top < 0) {
+ p.signalWork(q);
+ if ((u = (int)(p.ctl >>> 32)) >= 0 ||
+ (u >> UAC_SHIFT) >= 0)
+ break;
+ }
+ }
+ }
+ if (p.tryCompensate()) {
+ try {
+ do {} while (!blocker.isReleasable() &&
+ !blocker.block());
+ } finally {
+ p.incrementActiveCount();
+ }
+ break;
+ }
+ }
}
else {
- do {} while (!blocker.isReleasable() && !blocker.block());
+ do {} while (!blocker.isReleasable() &&
+ !blocker.block());
}
}
@@ -2074,54 +3250,93 @@
// implement RunnableFuture.
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
- return (RunnableFuture<T>) ForkJoinTask.adapt(runnable, value);
+ return new ForkJoinTask.AdaptedRunnable<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
- return (RunnableFuture<T>) ForkJoinTask.adapt(callable);
+ return new ForkJoinTask.AdaptedCallable<T>(callable);
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long ctlOffset;
- private static final long stealCountOffset;
- private static final long blockedCountOffset;
- private static final long quiescerCountOffset;
- private static final long scanGuardOffset;
- private static final long nextWorkerNumberOffset;
- private static final long ABASE;
+ private static final sun.misc.Unsafe U;
+ private static final long CTL;
+ private static final long PARKBLOCKER;
+ private static final int ABASE;
private static final int ASHIFT;
+ private static final long STEALCOUNT;
+ private static final long PLOCK;
+ private static final long INDEXSEED;
+ private static final long QLOCK;
static {
- poolNumberGenerator = new AtomicInteger();
- workerSeedGenerator = new Random();
- modifyThreadPermission = new RuntimePermission("modifyThread");
- defaultForkJoinWorkerThreadFactory =
- new DefaultForkJoinWorkerThreadFactory();
+ // initialize field offsets for CAS etc
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
+ U = sun.misc.Unsafe.getUnsafe();
Class<?> k = ForkJoinPool.class;
- ctlOffset = UNSAFE.objectFieldOffset
+ CTL = U.objectFieldOffset
(k.getDeclaredField("ctl"));
- stealCountOffset = UNSAFE.objectFieldOffset
+ STEALCOUNT = U.objectFieldOffset
(k.getDeclaredField("stealCount"));
- blockedCountOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("blockedCount"));
- quiescerCountOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("quiescerCount"));
- scanGuardOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("scanGuard"));
- nextWorkerNumberOffset = UNSAFE.objectFieldOffset
- (k.getDeclaredField("nextWorkerNumber"));
+ PLOCK = U.objectFieldOffset
+ (k.getDeclaredField("plock"));
+ INDEXSEED = U.objectFieldOffset
+ (k.getDeclaredField("indexSeed"));
+ Class<?> tk = Thread.class;
+ PARKBLOCKER = U.objectFieldOffset
+ (tk.getDeclaredField("parkBlocker"));
+ Class<?> wk = WorkQueue.class;
+ QLOCK = U.objectFieldOffset
+ (wk.getDeclaredField("qlock"));
+ Class<?> ak = ForkJoinTask[].class;
+ ABASE = U.arrayBaseOffset(ak);
+ int scale = U.arrayIndexScale(ak);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
} catch (Exception e) {
throw new Error(e);
}
- Class<?> a = ForkJoinTask[].class;
- ABASE = UNSAFE.arrayBaseOffset(a);
- int s = UNSAFE.arrayIndexScale(a);
- if ((s & (s-1)) != 0)
- throw new Error("data type scale not a power of two");
- ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
+
+ submitters = new ThreadLocal<Submitter>();
+ ForkJoinWorkerThreadFactory fac = defaultForkJoinWorkerThreadFactory =
+ new DefaultForkJoinWorkerThreadFactory();
+ modifyThreadPermission = new RuntimePermission("modifyThread");
+
+ /*
+ * Establish common pool parameters. For extra caution,
+ * computations to set up common pool state are here; the
+ * constructor just assigns these values to fields.
+ */
+
+ int par = 0;
+ Thread.UncaughtExceptionHandler handler = null;
+ try { // TBD: limit or report ignored exceptions?
+ String pp = System.getProperty
+ ("java.util.concurrent.ForkJoinPool.common.parallelism");
+ String hp = System.getProperty
+ ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
+ String fp = System.getProperty
+ ("java.util.concurrent.ForkJoinPool.common.threadFactory");
+ if (fp != null)
+ fac = ((ForkJoinWorkerThreadFactory)ClassLoader.
+ getSystemClassLoader().loadClass(fp).newInstance());
+ if (hp != null)
+ handler = ((Thread.UncaughtExceptionHandler)ClassLoader.
+ getSystemClassLoader().loadClass(hp).newInstance());
+ if (pp != null)
+ par = Integer.parseInt(pp);
+ } catch (Exception ignore) {
+ }
+
+ if (par <= 0)
+ par = Runtime.getRuntime().availableProcessors();
+ if (par > MAX_CAP)
+ par = MAX_CAP;
+ commonPoolParallelism = par;
+ long np = (long)(-par); // precompute initial ctl value
+ long ct = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
+
+ commonPool = new ForkJoinPool(par, ct, fac, handler);
}
}
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
index 86a29d7..818788e 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinTask.java
@@ -22,7 +22,6 @@
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
import java.lang.reflect.Constructor;
-import libcore.util.SneakyThrow;
/**
* Abstract base class for tasks that run within a {@link ForkJoinPool}.
@@ -31,46 +30,59 @@
* subtasks may be hosted by a small number of actual threads in a
* ForkJoinPool, at the price of some usage limitations.
*
- * <p>A "main" {@code ForkJoinTask} begins execution when submitted
- * to a {@link ForkJoinPool}. Once started, it will usually in turn
- * start other subtasks. As indicated by the name of this class,
- * many programs using {@code ForkJoinTask} employ only methods
- * {@link #fork} and {@link #join}, or derivatives such as {@link
+ * <p>A "main" {@code ForkJoinTask} begins execution when it is
+ * explicitly submitted to a {@link ForkJoinPool}, or, if not already
+ * engaged in a ForkJoin computation, commenced in the {@link
+ * ForkJoinPool#commonPool()} via {@link #fork}, {@link #invoke}, or
+ * related methods. Once started, it will usually in turn start other
+ * subtasks. As indicated by the name of this class, many programs
+ * using {@code ForkJoinTask} employ only methods {@link #fork} and
+ * {@link #join}, or derivatives such as {@link
* #invokeAll(ForkJoinTask...) invokeAll}. However, this class also
* provides a number of other methods that can come into play in
- * advanced usages, as well as extension mechanics that allow
- * support of new forms of fork/join processing.
+ * advanced usages, as well as extension mechanics that allow support
+ * of new forms of fork/join processing.
*
* <p>A {@code ForkJoinTask} is a lightweight form of {@link Future}.
* The efficiency of {@code ForkJoinTask}s stems from a set of
* restrictions (that are only partially statically enforceable)
- * reflecting their intended use as computational tasks calculating
- * pure functions or operating on purely isolated objects. The
- * primary coordination mechanisms are {@link #fork}, that arranges
+ * reflecting their main use as computational tasks calculating pure
+ * functions or operating on purely isolated objects. The primary
+ * coordination mechanisms are {@link #fork}, that arranges
* asynchronous execution, and {@link #join}, that doesn't proceed
* until the task's result has been computed. Computations should
- * avoid {@code synchronized} methods or blocks, and should minimize
- * other blocking synchronization apart from joining other tasks or
- * using synchronizers such as Phasers that are advertised to
- * cooperate with fork/join scheduling. Tasks should also not perform
- * blocking IO, and should ideally access variables that are
- * completely independent of those accessed by other running
- * tasks. Minor breaches of these restrictions, for example using
- * shared output streams, may be tolerable in practice, but frequent
- * use may result in poor performance, and the potential to
- * indefinitely stall if the number of threads not waiting for IO or
- * other external synchronization becomes exhausted. This usage
- * restriction is in part enforced by not permitting checked
- * exceptions such as {@code IOExceptions} to be thrown. However,
- * computations may still encounter unchecked exceptions, that are
- * rethrown to callers attempting to join them. These exceptions may
- * additionally include {@link RejectedExecutionException} stemming
- * from internal resource exhaustion, such as failure to allocate
- * internal task queues. Rethrown exceptions behave in the same way as
- * regular exceptions, but, when possible, contain stack traces (as
- * displayed for example using {@code ex.printStackTrace()}) of both
- * the thread that initiated the computation as well as the thread
- * actually encountering the exception; minimally only the latter.
+ * ideally avoid {@code synchronized} methods or blocks, and should
+ * minimize other blocking synchronization apart from joining other
+ * tasks or using synchronizers such as Phasers that are advertised to
+ * cooperate with fork/join scheduling. Subdividable tasks should also
+ * not perform blocking I/O, and should ideally access variables that
+ * are completely independent of those accessed by other running
+ * tasks. These guidelines are loosely enforced by not permitting
+ * checked exceptions such as {@code IOExceptions} to be
+ * thrown. However, computations may still encounter unchecked
+ * exceptions, that are rethrown to callers attempting to join
+ * them. These exceptions may additionally include {@link
+ * RejectedExecutionException} stemming from internal resource
+ * exhaustion, such as failure to allocate internal task
+ * queues. Rethrown exceptions behave in the same way as regular
+ * exceptions, but, when possible, contain stack traces (as displayed
+ * for example using {@code ex.printStackTrace()}) of both the thread
+ * that initiated the computation as well as the thread actually
+ * encountering the exception; minimally only the latter.
+ *
+ * <p>It is possible to define and use ForkJoinTasks that may block,
+ * but doing do requires three further considerations: (1) Completion
+ * of few if any <em>other</em> tasks should be dependent on a task
+ * that blocks on external synchronization or I/O. Event-style async
+ * tasks that are never joined (for example, those subclassing {@link
+ * CountedCompleter}) often fall into this category. (2) To minimize
+ * resource impact, tasks should be small; ideally performing only the
+ * (possibly) blocking action. (3) Unless the {@link
+ * ForkJoinPool.ManagedBlocker} API is used, or the number of possibly
+ * blocked tasks is known to be less than the pool's {@link
+ * ForkJoinPool#getParallelism} level, the pool cannot guarantee that
+ * enough threads will be available to ensure progress or good
+ * performance.
*
* <p>The primary method for awaiting completion and extracting
* results of a task is {@link #join}, but there are several variants:
@@ -86,6 +98,13 @@
* performs the most common form of parallel invocation: forking a set
* of tasks and joining them all.
*
+ * <p>In the most typical usages, a fork-join pair act like a call
+ * (fork) and return (join) from a parallel recursive function. As is
+ * the case with other forms of recursive calls, returns (joins)
+ * should be performed innermost-first. For example, {@code a.fork();
+ * b.fork(); b.join(); a.join();} is likely to be substantially more
+ * efficient than joining {@code a} before {@code b}.
+ *
* <p>The execution status of tasks may be queried at several levels
* of detail: {@link #isDone} is true if a task completed in any way
* (including the case where a task was cancelled without executing);
@@ -101,18 +120,13 @@
* <p>The ForkJoinTask class is not usually directly subclassed.
* Instead, you subclass one of the abstract classes that support a
* particular style of fork/join processing, typically {@link
- * RecursiveAction} for computations that do not return results, or
- * {@link RecursiveTask} for those that do. Normally, a concrete
- * ForkJoinTask subclass declares fields comprising its parameters,
- * established in a constructor, and then defines a {@code compute}
- * method that somehow uses the control methods supplied by this base
- * class. While these methods have {@code public} access (to allow
- * instances of different task subclasses to call each other's
- * methods), some of them may only be called from within other
- * ForkJoinTasks (as may be determined using method {@link
- * #inForkJoinPool}). Attempts to invoke them in other contexts
- * result in exceptions or errors, possibly including
- * {@code ClassCastException}.
+ * RecursiveAction} for most computations that do not return results,
+ * {@link RecursiveTask} for those that do, and {@link
+ * CountedCompleter} for those in which completed actions trigger
+ * other actions. Normally, a concrete ForkJoinTask subclass declares
+ * fields comprising its parameters, established in a constructor, and
+ * then defines a {@code compute} method that somehow uses the control
+ * methods supplied by this base class.
*
* <p>Method {@link #join} and its variants are appropriate for use
* only when completion dependencies are acyclic; that is, the
@@ -122,7 +136,17 @@
* supports other methods and techniques (for example the use of
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
- * are not statically structured as DAGs.
+ * are not statically structured as DAGs. To support such usages a
+ * ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
+ * value using {@link #setForkJoinTaskTag} or {@link
+ * #compareAndSetForkJoinTaskTag} and checked using {@link
+ * #getForkJoinTaskTag}. The ForkJoinTask implementation does not use
+ * these {@code protected} methods or tags for any purpose, but they
+ * may be of use in the construction of specialized subclasses. For
+ * example, parallel graph traversals can use the supplied methods to
+ * avoid revisiting nodes/tasks that have already been processed.
+ * (Method names for tagging are bulky in part to encourage definition
+ * of methods that reflect their usage patterns.)
*
* <p>Most base support methods are {@code final}, to prevent
* overriding of implementations that are intrinsically tied to the
@@ -177,29 +201,36 @@
* The status field holds run control status bits packed into a
* single int to minimize footprint and to ensure atomicity (via
* CAS). Status is initially zero, and takes on nonnegative
- * values until completed, upon which status holds value
- * NORMAL, CANCELLED, or EXCEPTIONAL. Tasks undergoing blocking
- * waits by other threads have the SIGNAL bit set. Completion of
- * a stolen task with SIGNAL set awakens any waiters via
- * notifyAll. Even though suboptimal for some purposes, we use
- * basic builtin wait/notify to take advantage of "monitor
- * inflation" in JVMs that we would otherwise need to emulate to
- * avoid adding further per-task bookkeeping overhead. We want
- * these monitors to be "fat", i.e., not use biasing or thin-lock
- * techniques, so use some odd coding idioms that tend to avoid
- * them.
+ * values until completed, upon which status (anded with
+ * DONE_MASK) holds value NORMAL, CANCELLED, or EXCEPTIONAL. Tasks
+ * undergoing blocking waits by other threads have the SIGNAL bit
+ * set. Completion of a stolen task with SIGNAL set awakens any
+ * waiters via notifyAll. Even though suboptimal for some
+ * purposes, we use basic builtin wait/notify to take advantage of
+ * "monitor inflation" in JVMs that we would otherwise need to
+ * emulate to avoid adding further per-task bookkeeping overhead.
+ * We want these monitors to be "fat", i.e., not use biasing or
+ * thin-lock techniques, so use some odd coding idioms that tend
+ * to avoid them, mainly by arranging that every synchronized
+ * block performs a wait, notifyAll or both.
+ *
+ * These control bits occupy only (some of) the upper half (16
+ * bits) of status field. The lower bits are used for user-defined
+ * tags.
*/
/** The run status of this task */
volatile int status; // accessed directly by pool and workers
- private static final int NORMAL = -1;
- private static final int CANCELLED = -2;
- private static final int EXCEPTIONAL = -3;
- private static final int SIGNAL = 1;
+ static final int DONE_MASK = 0xf0000000; // mask out non-completion bits
+ static final int NORMAL = 0xf0000000; // must be negative
+ static final int CANCELLED = 0xc0000000; // must be < NORMAL
+ static final int EXCEPTIONAL = 0x80000000; // must be < CANCELLED
+ static final int SIGNAL = 0x00010000; // must be >= 1 << 16
+ static final int SMASK = 0x0000ffff; // short bits for tags
/**
- * Marks completion and wakes up threads waiting to join this task,
- * also clearing signal request bits.
+ * Marks completion and wakes up threads waiting to join this
+ * task.
*
* @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
* @return completion status on exit
@@ -208,8 +239,8 @@
for (int s;;) {
if ((s = status) < 0)
return s;
- if (UNSAFE.compareAndSwapInt(this, statusOffset, s, completion)) {
- if (s != 0)
+ if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
+ if ((s >>> 16) != 0)
synchronized (this) { notifyAll(); }
return completion;
}
@@ -217,27 +248,36 @@
}
/**
- * Tries to block a worker thread until completed or timed out.
- * Uses Object.wait time argument conventions.
- * May fail on contention or interrupt.
+ * Primary execution method for stolen tasks. Unless done, calls
+ * exec and records status if completed, but doesn't wait for
+ * completion otherwise.
*
- * @param millis if > 0, wait time.
+ * @return status on exit from this method
*/
- final void tryAwaitDone(long millis) {
- int s;
- try {
- if (((s = status) > 0 ||
- (s == 0 &&
- UNSAFE.compareAndSwapInt(this, statusOffset, 0, SIGNAL))) &&
- status > 0) {
- synchronized (this) {
- if (status > 0)
- wait(millis);
- }
+ final int doExec() {
+ int s; boolean completed;
+ if ((s = status) >= 0) {
+ try {
+ completed = exec();
+ } catch (Throwable rex) {
+ return setExceptionalCompletion(rex);
}
- } catch (InterruptedException ie) {
- // caller must check termination
+ if (completed)
+ s = setCompletion(NORMAL);
}
+ return s;
+ }
+
+ /**
+ * Tries to set SIGNAL status unless already completed. Used by
+ * ForkJoinPool. Other variants are directly incorporated into
+ * externalAwaitDone etc.
+ *
+ * @return true if successful
+ */
+ final boolean trySetSignal() {
+ int s = status;
+ return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL);
}
/**
@@ -246,113 +286,78 @@
*/
private int externalAwaitDone() {
int s;
- if ((s = status) >= 0) {
- boolean interrupted = false;
- synchronized (this) {
- while ((s = status) >= 0) {
- if (s == 0)
- UNSAFE.compareAndSwapInt(this, statusOffset,
- 0, SIGNAL);
- else {
+ ForkJoinPool.externalHelpJoin(this);
+ boolean interrupted = false;
+ while ((s = status) >= 0) {
+ if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+ synchronized (this) {
+ if (status >= 0) {
try {
wait();
} catch (InterruptedException ie) {
interrupted = true;
}
}
+ else
+ notifyAll();
}
}
- if (interrupted)
- Thread.currentThread().interrupt();
}
+ if (interrupted)
+ Thread.currentThread().interrupt();
return s;
}
/**
- * Blocks a non-worker-thread until completion or interruption or timeout.
+ * Blocks a non-worker-thread until completion or interruption.
*/
- private int externalInterruptibleAwaitDone(long millis)
- throws InterruptedException {
+ private int externalInterruptibleAwaitDone() throws InterruptedException {
int s;
if (Thread.interrupted())
throw new InterruptedException();
- if ((s = status) >= 0) {
- synchronized (this) {
- while ((s = status) >= 0) {
- if (s == 0)
- UNSAFE.compareAndSwapInt(this, statusOffset,
- 0, SIGNAL);
- else {
- wait(millis);
- if (millis > 0L)
- break;
- }
+ ForkJoinPool.externalHelpJoin(this);
+ while ((s = status) >= 0) {
+ if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+ synchronized (this) {
+ if (status >= 0)
+ wait();
+ else
+ notifyAll();
}
}
}
return s;
}
- /**
- * Primary execution method for stolen tasks. Unless done, calls
- * exec and records status if completed, but doesn't wait for
- * completion otherwise.
- */
- final void doExec() {
- if (status >= 0) {
- boolean completed;
- try {
- completed = exec();
- } catch (Throwable rex) {
- setExceptionalCompletion(rex);
- return;
- }
- if (completed)
- setCompletion(NORMAL); // must be outside try block
- }
- }
/**
- * Primary mechanics for join, get, quietlyJoin.
+ * Implementation for join, get, quietlyJoin. Directly handles
+ * only cases of already-completed, external wait, and
+ * unfork+exec. Others are relayed to ForkJoinPool.awaitJoin.
+ *
* @return status upon completion
*/
private int doJoin() {
- Thread t; ForkJoinWorkerThread w; int s; boolean completed;
- if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
- if ((s = status) < 0)
- return s;
- if ((w = (ForkJoinWorkerThread)t).unpushTask(this)) {
- try {
- completed = exec();
- } catch (Throwable rex) {
- return setExceptionalCompletion(rex);
- }
- if (completed)
- return setCompletion(NORMAL);
- }
- return w.joinTask(this);
- }
- else
- return externalAwaitDone();
+ int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
+ return (s = status) < 0 ? s :
+ ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ (w = (wt = (ForkJoinWorkerThread)t).workQueue).
+ tryUnpush(this) && (s = doExec()) < 0 ? s :
+ wt.pool.awaitJoin(w, this) :
+ externalAwaitDone();
}
/**
- * Primary mechanics for invoke, quietlyInvoke.
+ * Implementation for invoke, quietlyInvoke.
+ *
* @return status upon completion
*/
private int doInvoke() {
- int s; boolean completed;
- if ((s = status) < 0)
- return s;
- try {
- completed = exec();
- } catch (Throwable rex) {
- return setExceptionalCompletion(rex);
- }
- if (completed)
- return setCompletion(NORMAL);
- else
- return doJoin();
+ int s; Thread t; ForkJoinWorkerThread wt;
+ return (s = doExec()) < 0 ? s :
+ ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) :
+ externalAwaitDone();
}
// Exception table support
@@ -387,7 +392,7 @@
* any ForkJoinPool will call helpExpungeStaleExceptions when its
* pool becomes isQuiescent.
*/
- static final class ExceptionNode extends WeakReference<ForkJoinTask<?>>{
+ static final class ExceptionNode extends WeakReference<ForkJoinTask<?>> {
final Throwable ex;
ExceptionNode next;
final long thrower; // use id not ref to avoid weak cycles
@@ -400,34 +405,71 @@
}
/**
- * Records exception and sets exceptional completion.
+ * Records exception and sets status.
+ *
+ * @return status on exit
+ */
+ final int recordExceptionalCompletion(Throwable ex) {
+ int s;
+ if ((s = status) >= 0) {
+ int h = System.identityHashCode(this);
+ final ReentrantLock lock = exceptionTableLock;
+ lock.lock();
+ try {
+ expungeStaleExceptions();
+ ExceptionNode[] t = exceptionTable;
+ int i = h & (t.length - 1);
+ for (ExceptionNode e = t[i]; ; e = e.next) {
+ if (e == null) {
+ t[i] = new ExceptionNode(this, ex, t[i]);
+ break;
+ }
+ if (e.get() == this) // already present
+ break;
+ }
+ } finally {
+ lock.unlock();
+ }
+ s = setCompletion(EXCEPTIONAL);
+ }
+ return s;
+ }
+
+ /**
+ * Records exception and possibly propagates.
*
* @return status on exit
*/
private int setExceptionalCompletion(Throwable ex) {
- int h = System.identityHashCode(this);
- final ReentrantLock lock = exceptionTableLock;
- lock.lock();
- try {
- expungeStaleExceptions();
- ExceptionNode[] t = exceptionTable;
- int i = h & (t.length - 1);
- for (ExceptionNode e = t[i]; ; e = e.next) {
- if (e == null) {
- t[i] = new ExceptionNode(this, ex, t[i]);
- break;
- }
- if (e.get() == this) // already present
- break;
- }
- } finally {
- lock.unlock();
- }
- return setCompletion(EXCEPTIONAL);
+ int s = recordExceptionalCompletion(ex);
+ if ((s & DONE_MASK) == EXCEPTIONAL)
+ internalPropagateException(ex);
+ return s;
}
/**
- * Removes exception node and clears status
+ * Hook for exception propagation support for tasks with completers.
+ */
+ void internalPropagateException(Throwable ex) {
+ }
+
+ /**
+ * Cancels, ignoring any exceptions thrown by cancel. Used during
+ * worker and pool shutdown. Cancel is spec'ed not to throw any
+ * exceptions, but if it does anyway, we have no recourse during
+ * shutdown, so guard against this case.
+ */
+ static final void cancelIgnoringExceptions(ForkJoinTask<?> t) {
+ if (t != null && t.status >= 0) {
+ try {
+ t.cancel(false);
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+
+ /**
+ * Removes exception node and clears status.
*/
private void clearExceptionalCompletion() {
int h = System.identityHashCode(this);
@@ -472,7 +514,7 @@
* @return the exception, or null if none
*/
private Throwable getThrowableException() {
- if (status != EXCEPTIONAL)
+ if ((status & DONE_MASK) != EXCEPTIONAL)
return null;
int h = System.identityHashCode(this);
ExceptionNode e;
@@ -490,7 +532,7 @@
Throwable ex;
if (e == null || (ex = e.ex) == null)
return null;
- if (e.thrower != Thread.currentThread().getId()) {
+ if (false && e.thrower != Thread.currentThread().getId()) {
Class<? extends Throwable> ec = ex.getClass();
try {
Constructor<?> noArgCtor = null;
@@ -557,41 +599,61 @@
}
/**
- * Report the result of invoke or join; called only upon
- * non-normal return of internal versions.
+ * A version of "sneaky throw" to relay exceptions
*/
- private V reportResult() {
- int s; Throwable ex;
- if ((s = status) == CANCELLED)
+ static void rethrow(final Throwable ex) {
+ if (ex != null) {
+ if (ex instanceof Error)
+ throw (Error)ex;
+ if (ex instanceof RuntimeException)
+ throw (RuntimeException)ex;
+ throw uncheckedThrowable(ex, RuntimeException.class);
+ }
+ }
+
+ /**
+ * The sneaky part of sneaky throw, relying on generics
+ * limitations to evade compiler complaints about rethrowing
+ * unchecked exceptions
+ */
+ @SuppressWarnings("unchecked") static <T extends Throwable>
+ T uncheckedThrowable(final Throwable t, final Class<T> c) {
+ return (T)t; // rely on vacuous cast
+ }
+
+ /**
+ * Throws exception, if any, associated with the given status.
+ */
+ private void reportException(int s) {
+ if (s == CANCELLED)
throw new CancellationException();
- if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
- SneakyThrow.sneakyThrow(ex); // android-changed
- return getRawResult();
+ if (s == EXCEPTIONAL)
+ rethrow(getThrowableException());
}
// public methods
/**
- * Arranges to asynchronously execute this task. While it is not
- * necessarily enforced, it is a usage error to fork a task more
- * than once unless it has completed and been reinitialized.
- * Subsequent modifications to the state of this task or any data
- * it operates on are not necessarily consistently observable by
- * any thread other than the one executing it unless preceded by a
- * call to {@link #join} or related methods, or a call to {@link
- * #isDone} returning {@code true}.
- *
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
+ * Arranges to asynchronously execute this task in the pool the
+ * current task is running in, if applicable, or using the {@link
+ * ForkJoinPool#commonPool()} if not {@link #inForkJoinPool}. While
+ * it is not necessarily enforced, it is a usage error to fork a
+ * task more than once unless it has completed and been
+ * reinitialized. Subsequent modifications to the state of this
+ * task or any data it operates on are not necessarily
+ * consistently observable by any thread other than the one
+ * executing it unless preceded by a call to {@link #join} or
+ * related methods, or a call to {@link #isDone} returning {@code
+ * true}.
*
* @return {@code this}, to simplify usage
*/
public final ForkJoinTask<V> fork() {
- ((ForkJoinWorkerThread) Thread.currentThread())
- .pushTask(this);
+ Thread t;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+ ((ForkJoinWorkerThread)t).workQueue.push(this);
+ else
+ ForkJoinPool.commonPool.externalPush(this);
return this;
}
@@ -607,10 +669,10 @@
* @return the computed result
*/
public final V join() {
- if (doJoin() != NORMAL)
- return reportResult();
- else
- return getRawResult();
+ int s;
+ if ((s = doJoin() & DONE_MASK) != NORMAL)
+ reportException(s);
+ return getRawResult();
}
/**
@@ -622,10 +684,10 @@
* @return the computed result
*/
public final V invoke() {
- if (doInvoke() != NORMAL)
- return reportResult();
- else
- return getRawResult();
+ int s;
+ if ((s = doInvoke() & DONE_MASK) != NORMAL)
+ reportException(s);
+ return getRawResult();
}
/**
@@ -641,20 +703,17 @@
* cancelled, completed normally or exceptionally, or left
* unprocessed.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @param t1 the first task
* @param t2 the second task
* @throws NullPointerException if any task is null
*/
public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {
+ int s1, s2;
t2.fork();
- t1.invoke();
- t2.join();
+ if ((s1 = t1.doInvoke() & DONE_MASK) != NORMAL)
+ t1.reportException(s1);
+ if ((s2 = t2.doJoin() & DONE_MASK) != NORMAL)
+ t2.reportException(s2);
}
/**
@@ -669,12 +728,6 @@
* related methods to check if they have been cancelled, completed
* normally or exceptionally, or left unprocessed.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @param tasks the tasks
* @throws NullPointerException if any task is null
*/
@@ -702,7 +755,7 @@
}
}
if (ex != null)
- SneakyThrow.sneakyThrow(ex); // android-changed
+ rethrow(ex);
}
/**
@@ -718,15 +771,11 @@
* cancelled, completed normally or exceptionally, or left
* unprocessed.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @param tasks the collection of tasks
* @return the tasks argument, to simplify usage
* @throws NullPointerException if tasks or any element are null
+
+ * @hide
*/
public static <T extends ForkJoinTask<?>> Collection<T> invokeAll(Collection<T> tasks) {
if (!(tasks instanceof RandomAccess) || !(tasks instanceof List<?>)) {
@@ -759,7 +808,7 @@
}
}
if (ex != null)
- SneakyThrow.sneakyThrow(ex); // android-changed
+ rethrow(ex);
return tasks;
}
@@ -791,20 +840,7 @@
* @return {@code true} if this task is now cancelled
*/
public boolean cancel(boolean mayInterruptIfRunning) {
- return setCompletion(CANCELLED) == CANCELLED;
- }
-
- /**
- * Cancels, ignoring any exceptions thrown by cancel. Used during
- * worker and pool shutdown. Cancel is spec'ed not to throw any
- * exceptions, but if it does anyway, we have no recourse during
- * shutdown, so guard against this case.
- */
- final void cancelIgnoringExceptions() {
- try {
- cancel(false);
- } catch (Throwable ignore) {
- }
+ return (setCompletion(CANCELLED) & DONE_MASK) == CANCELLED;
}
public final boolean isDone() {
@@ -812,7 +848,7 @@
}
public final boolean isCancelled() {
- return status == CANCELLED;
+ return (status & DONE_MASK) == CANCELLED;
}
/**
@@ -832,7 +868,7 @@
* exception and was not cancelled
*/
public final boolean isCompletedNormally() {
- return status == NORMAL;
+ return (status & DONE_MASK) == NORMAL;
}
/**
@@ -843,7 +879,7 @@
* @return the exception, or {@code null} if none
*/
public final Throwable getException() {
- int s = status;
+ int s = status & DONE_MASK;
return ((s >= NORMAL) ? null :
(s == CANCELLED) ? new CancellationException() :
getThrowableException());
@@ -893,6 +929,19 @@
}
/**
+ * Completes this task normally without setting a value. The most
+ * recent value established by {@link #setRawResult} (or {@code
+ * null} by default) will be returned as the result of subsequent
+ * invocations of {@code join} and related operations.
+ *
+ * @since 1.8
+ * @hide
+ */
+ public final void quietlyComplete() {
+ setCompletion(NORMAL);
+ }
+
+ /**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
@@ -905,9 +954,9 @@
*/
public final V get() throws InterruptedException, ExecutionException {
int s = (Thread.currentThread() instanceof ForkJoinWorkerThread) ?
- doJoin() : externalInterruptibleAwaitDone(0L);
+ doJoin() : externalInterruptibleAwaitDone();
Throwable ex;
- if (s == CANCELLED)
+ if ((s &= DONE_MASK) == CANCELLED)
throw new CancellationException();
if (s == EXCEPTIONAL && (ex = getThrowableException()) != null)
throw new ExecutionException(ex);
@@ -930,32 +979,63 @@
*/
public final V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
- Thread t = Thread.currentThread();
- if (t instanceof ForkJoinWorkerThread) {
- ForkJoinWorkerThread w = (ForkJoinWorkerThread) t;
- long nanos = unit.toNanos(timeout);
- if (status >= 0) {
- boolean completed = false;
- if (w.unpushTask(this)) {
- try {
- completed = exec();
- } catch (Throwable rex) {
- setExceptionalCompletion(rex);
+ if (Thread.interrupted())
+ throw new InterruptedException();
+ // Messy in part because we measure in nanosecs, but wait in millisecs
+ int s; long ms;
+ long ns = unit.toNanos(timeout);
+ if ((s = status) >= 0 && ns > 0L) {
+ long deadline = System.nanoTime() + ns;
+ ForkJoinPool p = null;
+ ForkJoinPool.WorkQueue w = null;
+ Thread t = Thread.currentThread();
+ if (t instanceof ForkJoinWorkerThread) {
+ ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
+ p = wt.pool;
+ w = wt.workQueue;
+ p.helpJoinOnce(w, this); // no retries on failure
+ }
+ else
+ ForkJoinPool.externalHelpJoin(this);
+ boolean canBlock = false;
+ boolean interrupted = false;
+ try {
+ while ((s = status) >= 0) {
+ if (w != null && w.qlock < 0)
+ cancelIgnoringExceptions(this);
+ else if (!canBlock) {
+ if (p == null || p.tryCompensate())
+ canBlock = true;
+ }
+ else {
+ if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
+ U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+ synchronized (this) {
+ if (status >= 0) {
+ try {
+ wait(ms);
+ } catch (InterruptedException ie) {
+ if (p == null)
+ interrupted = true;
+ }
+ }
+ else
+ notifyAll();
+ }
+ }
+ if ((s = status) < 0 || interrupted ||
+ (ns = deadline - System.nanoTime()) <= 0L)
+ break;
}
}
- if (completed)
- setCompletion(NORMAL);
- else if (status >= 0 && nanos > 0)
- w.pool.timedAwaitJoin(this, nanos);
+ } finally {
+ if (p != null && canBlock)
+ p.incrementActiveCount();
}
+ if (interrupted)
+ throw new InterruptedException();
}
- else {
- long millis = unit.toMillis(timeout);
- if (millis > 0)
- externalInterruptibleAwaitDone(millis);
- }
- int s = status;
- if (s != NORMAL) {
+ if ((s &= DONE_MASK) != NORMAL) {
Throwable ex;
if (s == CANCELLED)
throw new CancellationException();
@@ -992,16 +1072,15 @@
* be of use in designs in which many tasks are forked, but none
* are explicitly joined, instead executing them until all are
* processed.
- *
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
*/
public static void helpQuiesce() {
- ((ForkJoinWorkerThread) Thread.currentThread())
- .helpQuiescePool();
+ Thread t;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
+ ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t;
+ wt.pool.helpQuiescePool(wt.workQueue);
+ }
+ else
+ ForkJoinPool.externalHelpQuiescePool();
}
/**
@@ -1021,7 +1100,7 @@
* setRawResult(null)}.
*/
public void reinitialize() {
- if (status == EXCEPTIONAL)
+ if ((status & DONE_MASK) == EXCEPTIONAL)
clearExceptionalCompletion();
else
status = 0;
@@ -1054,23 +1133,19 @@
/**
* Tries to unschedule this task for execution. This method will
- * typically succeed if this task is the most recently forked task
- * by the current thread, and has not commenced executing in
- * another thread. This method may be useful when arranging
- * alternative local processing of tasks that could have been, but
- * were not, stolen.
- *
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
+ * typically (but is not guaranteed to) succeed if this task is
+ * the most recently forked task by the current thread, and has
+ * not commenced executing in another thread. This method may be
+ * useful when arranging alternative local processing of tasks
+ * that could have been, but were not, stolen.
*
* @return {@code true} if unforked
*/
public boolean tryUnfork() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .unpushTask(this);
+ Thread t;
+ return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ ((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) :
+ ForkJoinPool.tryExternalUnpush(this));
}
/**
@@ -1079,40 +1154,32 @@
* value may be useful for heuristic decisions about whether to
* fork other tasks.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @return the number of tasks
*/
public static int getQueuedTaskCount() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .getQueueSize();
+ Thread t; ForkJoinPool.WorkQueue q;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+ q = ((ForkJoinWorkerThread)t).workQueue;
+ else
+ q = ForkJoinPool.commonSubmitterQueue();
+ return (q == null) ? 0 : q.queueSize();
}
/**
* Returns an estimate of how many more locally queued tasks are
* held by the current worker thread than there are other worker
- * threads that might steal them. This value may be useful for
+ * threads that might steal them, or zero if this thread is not
+ * operating in a ForkJoinPool. This value may be useful for
* heuristic decisions about whether to fork other tasks. In many
* usages of ForkJoinTasks, at steady state, each worker should
* aim to maintain a small constant surplus (for example, 3) of
* tasks, and to process computations locally if this threshold is
* exceeded.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @return the surplus number of tasks, which may be negative
*/
public static int getSurplusQueuedTaskCount() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .getEstimatedSurplusTaskCount();
+ return ForkJoinPool.getSurplusQueuedTaskCount();
}
// Extension methods
@@ -1138,15 +1205,18 @@
protected abstract void setRawResult(V value);
/**
- * Immediately performs the base action of this task. This method
- * is designed to support extensions, and should not in general be
- * called otherwise. The return value controls whether this task
- * is considered to be done normally. It may return false in
+ * Immediately performs the base action of this task and returns
+ * true if, upon return from this method, this task is guaranteed
+ * to have completed normally. This method may return false
+ * otherwise, to indicate that this task is not necessarily
+ * complete (or is not known to be complete), for example in
* asynchronous actions that require explicit invocations of
- * {@link #complete} to become joinable. It may also throw an
- * (unchecked) exception to indicate abnormal exit.
+ * completion methods. This method may also throw an (unchecked)
+ * exception to indicate abnormal exit. This method is designed to
+ * support extensions, and should not in general be called
+ * otherwise.
*
- * @return {@code true} if completed normally
+ * @return {@code true} if this task is known to have completed normally
*/
protected abstract boolean exec();
@@ -1160,59 +1230,105 @@
* primarily to support extensions, and is unlikely to be useful
* otherwise.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @return the next task, or {@code null} if none are available
*/
protected static ForkJoinTask<?> peekNextLocalTask() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .peekTask();
+ Thread t; ForkJoinPool.WorkQueue q;
+ if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)
+ q = ((ForkJoinWorkerThread)t).workQueue;
+ else
+ q = ForkJoinPool.commonSubmitterQueue();
+ return (q == null) ? null : q.peek();
}
/**
* Unschedules and returns, without executing, the next task
- * queued by the current thread but not yet executed. This method
- * is designed primarily to support extensions, and is unlikely to
- * be useful otherwise.
- *
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
+ * queued by the current thread but not yet executed, if the
+ * current thread is operating in a ForkJoinPool. This method is
+ * designed primarily to support extensions, and is unlikely to be
+ * useful otherwise.
*
* @return the next task, or {@code null} if none are available
*/
protected static ForkJoinTask<?> pollNextLocalTask() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .pollLocalTask();
+ Thread t;
+ return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ ((ForkJoinWorkerThread)t).workQueue.nextLocalTask() :
+ null;
}
/**
- * Unschedules and returns, without executing, the next task
+ * If the current thread is operating in a ForkJoinPool,
+ * unschedules and returns, without executing, the next task
* queued by the current thread but not yet executed, if one is
* available, or if not available, a task that was forked by some
* other thread, if available. Availability may be transient, so a
- * {@code null} result does not necessarily imply quiescence
- * of the pool this task is operating in. This method is designed
+ * {@code null} result does not necessarily imply quiescence of
+ * the pool this task is operating in. This method is designed
* primarily to support extensions, and is unlikely to be useful
* otherwise.
*
- * <p>This method may be invoked only from within {@code
- * ForkJoinPool} computations (as may be determined using method
- * {@link #inForkJoinPool}). Attempts to invoke in other contexts
- * result in exceptions or errors, possibly including {@code
- * ClassCastException}.
- *
* @return a task, or {@code null} if none are available
*/
protected static ForkJoinTask<?> pollTask() {
- return ((ForkJoinWorkerThread) Thread.currentThread())
- .pollTask();
+ Thread t; ForkJoinWorkerThread wt;
+ return ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
+ (wt = (ForkJoinWorkerThread)t).pool.nextTaskFor(wt.workQueue) :
+ null;
+ }
+
+ // tag operations
+
+ /**
+ * Returns the tag for this task.
+ *
+ * @return the tag for this task
+ * @since 1.8
+ * @hide
+ */
+ public final short getForkJoinTaskTag() {
+ return (short)status;
+ }
+
+ /**
+ * Atomically sets the tag value for this task.
+ *
+ * @param tag the tag value
+ * @return the previous value of the tag
+ * @since 1.8
+ * @hide
+ */
+ public final short setForkJoinTaskTag(short tag) {
+ for (int s;;) {
+ if (U.compareAndSwapInt(this, STATUS, s = status,
+ (s & ~SMASK) | (tag & SMASK)))
+ return (short)s;
+ }
+ }
+
+ /**
+ * Atomically conditionally sets the tag value for this task.
+ * Among other applications, tags can be used as visit markers
+ * in tasks operating on graphs, as in methods that check: {@code
+ * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))}
+ * before processing, otherwise exiting because the node has
+ * already been visited.
+ *
+ * @param e the expected tag value
+ * @param tag the new tag value
+ * @return true if successful; i.e., the current value was
+ * equal to e and is now tag.
+ * @since 1.8
+ * @hide
+ */
+ public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
+ for (int s;;) {
+ if ((short)(s = status) != e)
+ return false;
+ if (U.compareAndSwapInt(this, STATUS, s,
+ (s & ~SMASK) | (tag & SMASK)))
+ return true;
+ }
}
/**
@@ -1223,21 +1339,33 @@
static final class AdaptedRunnable<T> extends ForkJoinTask<T>
implements RunnableFuture<T> {
final Runnable runnable;
- final T resultOnCompletion;
T result;
AdaptedRunnable(Runnable runnable, T result) {
if (runnable == null) throw new NullPointerException();
this.runnable = runnable;
- this.resultOnCompletion = result;
+ this.result = result; // OK to set this even before completion
}
- public T getRawResult() { return result; }
- public void setRawResult(T v) { result = v; }
- public boolean exec() {
- runnable.run();
- result = resultOnCompletion;
- return true;
+ public final T getRawResult() { return result; }
+ public final void setRawResult(T v) { result = v; }
+ public final boolean exec() { runnable.run(); return true; }
+ public final void run() { invoke(); }
+ private static final long serialVersionUID = 5232453952276885070L;
+ }
+
+ /**
+ * Adaptor for Runnables without results
+ */
+ static final class AdaptedRunnableAction extends ForkJoinTask<Void>
+ implements RunnableFuture<Void> {
+ final Runnable runnable;
+ AdaptedRunnableAction(Runnable runnable) {
+ if (runnable == null) throw new NullPointerException();
+ this.runnable = runnable;
}
- public void run() { invoke(); }
+ public final Void getRawResult() { return null; }
+ public final void setRawResult(Void v) { }
+ public final boolean exec() { runnable.run(); return true; }
+ public final void run() { invoke(); }
private static final long serialVersionUID = 5232453952276885070L;
}
@@ -1252,9 +1380,9 @@
if (callable == null) throw new NullPointerException();
this.callable = callable;
}
- public T getRawResult() { return result; }
- public void setRawResult(T v) { result = v; }
- public boolean exec() {
+ public final T getRawResult() { return result; }
+ public final void setRawResult(T v) { result = v; }
+ public final boolean exec() {
try {
result = callable.call();
return true;
@@ -1266,7 +1394,7 @@
throw new RuntimeException(ex);
}
}
- public void run() { invoke(); }
+ public final void run() { invoke(); }
private static final long serialVersionUID = 2838392045355241008L;
}
@@ -1279,7 +1407,7 @@
* @return the task
*/
public static ForkJoinTask<?> adapt(Runnable runnable) {
- return new AdaptedRunnable<Void>(runnable, null);
+ return new AdaptedRunnableAction(runnable);
}
/**
@@ -1313,11 +1441,10 @@
private static final long serialVersionUID = -7721805057305804111L;
/**
- * Saves the state to a stream (that is, serializes it).
+ * Saves this task to a stream (that is, serializes it).
*
* @serialData the current run status and the exception thrown
* during execution, or {@code null} if none
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1326,9 +1453,7 @@
}
/**
- * Reconstitutes the instance from a stream (that is, deserializes it).
- *
- * @param s the stream
+ * Reconstitutes this task from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -1339,16 +1464,18 @@
}
// Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long statusOffset;
+ private static final sun.misc.Unsafe U;
+ private static final long STATUS;
+
static {
exceptionTableLock = new ReentrantLock();
exceptionTableRefQueue = new ReferenceQueue<Object>();
exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- statusOffset = UNSAFE.objectFieldOffset
- (ForkJoinTask.class.getDeclaredField("status"));
+ U = sun.misc.Unsafe.getUnsafe();
+ Class<?> k = ForkJoinTask.class;
+ STATUS = U.objectFieldOffset
+ (k.getDeclaredField("status"));
} catch (Exception e) {
throw new Error(e);
}
diff --git a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
index d99ffe9..f31763c 100644
--- a/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
+++ b/luni/src/main/java/java/util/concurrent/ForkJoinWorkerThread.java
@@ -6,10 +6,6 @@
package java.util.concurrent;
-import java.util.Collection;
-import java.util.concurrent.RejectedExecutionException;
-import libcore.util.SneakyThrow;
-
/**
* A thread managed by a {@link ForkJoinPool}, which executes
* {@link ForkJoinTask}s.
@@ -27,238 +23,20 @@
*/
public class ForkJoinWorkerThread extends Thread {
/*
- * Overview:
- *
* ForkJoinWorkerThreads are managed by ForkJoinPools and perform
- * ForkJoinTasks. This class includes bookkeeping in support of
- * worker activation, suspension, and lifecycle control described
- * in more detail in the internal documentation of class
- * ForkJoinPool. And as described further below, this class also
- * includes special-cased support for some ForkJoinTask
- * methods. But the main mechanics involve work-stealing:
+ * ForkJoinTasks. For explanation, see the internal documentation
+ * of class ForkJoinPool.
*
- * Work-stealing queues are special forms of Deques that support
- * only three of the four possible end-operations -- push, pop,
- * and deq (aka steal), under the further constraints that push
- * and pop are called only from the owning thread, while deq may
- * be called from other threads. (If you are unfamiliar with
- * them, you probably want to read Herlihy and Shavit's book "The
- * Art of Multiprocessor programming", chapter 16 describing these
- * in more detail before proceeding.) The main work-stealing
- * queue design is roughly similar to those in the papers "Dynamic
- * Circular Work-Stealing Deque" by Chase and Lev, SPAA 2005
- * (http://research.sun.com/scalable/pubs/index.html) and
- * "Idempotent work stealing" by Michael, Saraswat, and Vechev,
- * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186).
- * The main differences ultimately stem from gc requirements that
- * we null out taken slots as soon as we can, to maintain as small
- * a footprint as possible even in programs generating huge
- * numbers of tasks. To accomplish this, we shift the CAS
- * arbitrating pop vs deq (steal) from being on the indices
- * ("queueBase" and "queueTop") to the slots themselves (mainly
- * via method "casSlotNull()"). So, both a successful pop and deq
- * mainly entail a CAS of a slot from non-null to null. Because
- * we rely on CASes of references, we do not need tag bits on
- * queueBase or queueTop. They are simple ints as used in any
- * circular array-based queue (see for example ArrayDeque).
- * Updates to the indices must still be ordered in a way that
- * guarantees that queueTop == queueBase means the queue is empty,
- * but otherwise may err on the side of possibly making the queue
- * appear nonempty when a push, pop, or deq have not fully
- * committed. Note that this means that the deq operation,
- * considered individually, is not wait-free. One thief cannot
- * successfully continue until another in-progress one (or, if
- * previously empty, a push) completes. However, in the
- * aggregate, we ensure at least probabilistic non-blockingness.
- * If an attempted steal fails, a thief always chooses a different
- * random victim target to try next. So, in order for one thief to
- * progress, it suffices for any in-progress deq or new push on
- * any empty queue to complete.
- *
- * This approach also enables support for "async mode" where local
- * task processing is in FIFO, not LIFO order; simply by using a
- * version of deq rather than pop when locallyFifo is true (as set
- * by the ForkJoinPool). This allows use in message-passing
- * frameworks in which tasks are never joined. However neither
- * mode considers affinities, loads, cache localities, etc, so
- * rarely provide the best possible performance on a given
- * machine, but portably provide good throughput by averaging over
- * these factors. (Further, even if we did try to use such
- * information, we do not usually have a basis for exploiting
- * it. For example, some sets of tasks profit from cache
- * affinities, but others are harmed by cache pollution effects.)
- *
- * When a worker would otherwise be blocked waiting to join a
- * task, it first tries a form of linear helping: Each worker
- * records (in field currentSteal) the most recent task it stole
- * from some other worker. Plus, it records (in field currentJoin)
- * the task it is currently actively joining. Method joinTask uses
- * these markers to try to find a worker to help (i.e., steal back
- * a task from and execute it) that could hasten completion of the
- * actively joined task. In essence, the joiner executes a task
- * that would be on its own local deque had the to-be-joined task
- * not been stolen. This may be seen as a conservative variant of
- * the approach in Wagner & Calder "Leapfrogging: a portable
- * technique for implementing efficient futures" SIGPLAN Notices,
- * 1993 (http://portal.acm.org/citation.cfm?id=155354). It differs
- * in that: (1) We only maintain dependency links across workers
- * upon steals, rather than use per-task bookkeeping. This may
- * require a linear scan of workers array to locate stealers, but
- * usually doesn't because stealers leave hints (that may become
- * stale/wrong) of where to locate them. This isolates cost to
- * when it is needed, rather than adding to per-task overhead.
- * (2) It is "shallow", ignoring nesting and potentially cyclic
- * mutual steals. (3) It is intentionally racy: field currentJoin
- * is updated only while actively joining, which means that we
- * miss links in the chain during long-lived tasks, GC stalls etc
- * (which is OK since blocking in such cases is usually a good
- * idea). (4) We bound the number of attempts to find work (see
- * MAX_HELP) and fall back to suspending the worker and if
- * necessary replacing it with another.
- *
- * Efficient implementation of these algorithms currently relies
- * on an uncomfortable amount of "Unsafe" mechanics. To maintain
- * correct orderings, reads and writes of variable queueBase
- * require volatile ordering. Variable queueTop need not be
- * volatile because non-local reads always follow those of
- * queueBase. Similarly, because they are protected by volatile
- * queueBase reads, reads of the queue array and its slots by
- * other threads do not need volatile load semantics, but writes
- * (in push) require store order and CASes (in pop and deq)
- * require (volatile) CAS semantics. (Michael, Saraswat, and
- * Vechev's algorithm has similar properties, but without support
- * for nulling slots.) Since these combinations aren't supported
- * using ordinary volatiles, the only way to accomplish these
- * efficiently is to use direct Unsafe calls. (Using external
- * AtomicIntegers and AtomicReferenceArrays for the indices and
- * array is significantly slower because of memory locality and
- * indirection effects.)
- *
- * Further, performance on most platforms is very sensitive to
- * placement and sizing of the (resizable) queue array. Even
- * though these queues don't usually become all that big, the
- * initial size must be large enough to counteract cache
- * contention effects across multiple queues (especially in the
- * presence of GC cardmarking). Also, to improve thread-locality,
- * queues are initialized after starting.
+ * This class just maintains links to its pool and WorkQueue. The
+ * pool field is set immediately upon construction, but the
+ * workQueue field is not set until a call to registerWorker
+ * completes. This leads to a visibility race, that is tolerated
+ * by requiring that the workQueue field is only accessed by the
+ * owning thread.
*/
- /**
- * Mask for pool indices encoded as shorts
- */
- private static final int SMASK = 0xffff;
-
- /**
- * Capacity of work-stealing queue array upon initialization.
- * Must be a power of two. Initial size must be at least 4, but is
- * padded to minimize cache effects.
- */
- private static final int INITIAL_QUEUE_CAPACITY = 1 << 13;
-
- /**
- * Maximum size for queue array. Must be a power of two
- * less than or equal to 1 << (31 - width of array entry) to
- * ensure lack of index wraparound, but is capped at a lower
- * value to help users trap runaway computations.
- */
- private static final int MAXIMUM_QUEUE_CAPACITY = 1 << 24; // 16M
-
- /**
- * The work-stealing queue array. Size must be a power of two.
- * Initialized when started (as opposed to when constructed), to
- * improve memory locality.
- */
- ForkJoinTask<?>[] queue;
-
- /**
- * The pool this thread works in. Accessed directly by ForkJoinTask.
- */
- final ForkJoinPool pool;
-
- /**
- * Index (mod queue.length) of next queue slot to push to or pop
- * from. It is written only by owner thread, and accessed by other
- * threads only after reading (volatile) queueBase. Both queueTop
- * and queueBase are allowed to wrap around on overflow, but
- * (queueTop - queueBase) still estimates size.
- */
- int queueTop;
-
- /**
- * Index (mod queue.length) of least valid queue slot, which is
- * always the next position to steal from if nonempty.
- */
- volatile int queueBase;
-
- /**
- * The index of most recent stealer, used as a hint to avoid
- * traversal in method helpJoinTask. This is only a hint because a
- * worker might have had multiple steals and this only holds one
- * of them (usually the most current). Declared non-volatile,
- * relying on other prevailing sync to keep reasonably current.
- */
- int stealHint;
-
- /**
- * Index of this worker in pool array. Set once by pool before
- * running, and accessed directly by pool to locate this worker in
- * its workers array.
- */
- final int poolIndex;
-
- /**
- * Encoded record for pool task waits. Usages are always
- * surrounded by volatile reads/writes
- */
- int nextWait;
-
- /**
- * Complement of poolIndex, offset by count of entries of task
- * waits. Accessed by ForkJoinPool to manage event waiters.
- */
- volatile int eventCount;
-
- /**
- * Seed for random number generator for choosing steal victims.
- * Uses Marsaglia xorshift. Must be initialized as nonzero.
- */
- int seed;
-
- /**
- * Number of steals. Directly accessed (and reset) by pool when
- * idle.
- */
- int stealCount;
-
- /**
- * True if this worker should or did terminate
- */
- volatile boolean terminate;
-
- /**
- * Set to true before LockSupport.park; false on return
- */
- volatile boolean parked;
-
- /**
- * True if use local fifo, not default lifo, for local polling.
- * Shadows value from ForkJoinPool.
- */
- final boolean locallyFifo;
-
- /**
- * The task most recently stolen from another worker (or
- * submission queue). All uses are surrounded by enough volatile
- * reads/writes to maintain as non-volatile.
- */
- ForkJoinTask<?> currentSteal;
-
- /**
- * The task currently being joined, set only when actively trying
- * to help other stealers in helpJoinTask. All uses are surrounded
- * by enough volatile reads/writes to maintain as non-volatile.
- */
- ForkJoinTask<?> currentJoin;
+ final ForkJoinPool pool; // the pool this thread works in
+ final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics
/**
* Creates a ForkJoinWorkerThread operating in the given pool.
@@ -267,20 +45,12 @@
* @throws NullPointerException if pool is null
*/
protected ForkJoinWorkerThread(ForkJoinPool pool) {
- super(pool.nextWorkerName());
+ // Use a placeholder until a useful name can be set in registerWorker
+ super("aForkJoinWorkerThread");
this.pool = pool;
- int k = pool.registerWorker(this);
- poolIndex = k;
- eventCount = ~k & SMASK; // clear wait count
- locallyFifo = pool.locallyFifo;
- Thread.UncaughtExceptionHandler ueh = pool.ueh;
- if (ueh != null)
- setUncaughtExceptionHandler(ueh);
- setDaemon(true);
+ this.workQueue = pool.registerWorker(this);
}
- // Public methods
-
/**
* Returns the pool hosting this thread.
*
@@ -300,28 +70,9 @@
* @return the index number
*/
public int getPoolIndex() {
- return poolIndex;
+ return workQueue.poolIndex;
}
- // Randomization
-
- /**
- * Computes next value for random victim probes and backoffs.
- * Scans don't require a very high quality generator, but also not
- * a crummy one. Marsaglia xor-shift is cheap and works well
- * enough. Note: This is manually inlined in FJP.scan() to avoid
- * writes inside busy loops.
- */
- private int nextSeed() {
- int r = seed;
- r ^= r << 13;
- r ^= r >>> 17;
- r ^= r << 5;
- return seed = r;
- }
-
- // Run State management
-
/**
* Initializes internal state after construction but before
* processing any tasks. If you override this method, you must
@@ -332,9 +83,6 @@
* processing tasks.
*/
protected void onStart() {
- queue = new ForkJoinTask<?>[INITIAL_QUEUE_CAPACITY];
- int r = ForkJoinPool.workerSeedGenerator.nextInt();
- seed = (r == 0) ? 1 : r; // must be nonzero
}
/**
@@ -346,17 +94,6 @@
* to an unrecoverable error, or {@code null} if completed normally
*/
protected void onTermination(Throwable exception) {
- try {
- terminate = true;
- cancelTasks();
- pool.deregisterWorker(this, exception);
- } catch (Throwable ex) { // Shouldn't ever happen
- if (exception == null) // but if so, at least rethrown
- exception = ex;
- } finally {
- if (exception != null)
- SneakyThrow.sneakyThrow(exception); // android-changed
- }
}
/**
@@ -368,603 +105,18 @@
Throwable exception = null;
try {
onStart();
- pool.work(this);
+ pool.runWorker(workQueue);
} catch (Throwable ex) {
exception = ex;
} finally {
- onTermination(exception);
- }
- }
-
- /*
- * Intrinsics-based atomic writes for queue slots. These are
- * basically the same as methods in AtomicReferenceArray, but
- * specialized for (1) ForkJoinTask elements (2) requirement that
- * nullness and bounds checks have already been performed by
- * callers and (3) effective offsets are known not to overflow
- * from int to long (because of MAXIMUM_QUEUE_CAPACITY). We don't
- * need corresponding version for reads: plain array reads are OK
- * because they are protected by other volatile reads and are
- * confirmed by CASes.
- *
- * Most uses don't actually call these methods, but instead
- * contain inlined forms that enable more predictable
- * optimization. We don't define the version of write used in
- * pushTask at all, but instead inline there a store-fenced array
- * slot write.
- *
- * Also in most methods, as a performance (not correctness) issue,
- * we'd like to encourage compilers not to arbitrarily postpone
- * setting queueTop after writing slot. Currently there is no
- * intrinsic for arranging this, but using Unsafe putOrderedInt
- * may be a preferable strategy on some compilers even though its
- * main effect is a pre-, not post- fence. To simplify possible
- * changes, the option is left in comments next to the associated
- * assignments.
- */
-
- /**
- * CASes slot i of array q from t to null. Caller must ensure q is
- * non-null and index is in range.
- */
- private static final boolean casSlotNull(ForkJoinTask<?>[] q, int i,
- ForkJoinTask<?> t) {
- return UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null);
- }
-
- /**
- * Performs a volatile write of the given task at given slot of
- * array q. Caller must ensure q is non-null and index is in
- * range. This method is used only during resets and backouts.
- */
- private static final void writeSlot(ForkJoinTask<?>[] q, int i,
- ForkJoinTask<?> t) {
- UNSAFE.putObjectVolatile(q, (i << ASHIFT) + ABASE, t);
- }
-
- // queue methods
-
- /**
- * Pushes a task. Call only from this thread.
- *
- * @param t the task. Caller must ensure non-null.
- */
- final void pushTask(ForkJoinTask<?> t) {
- ForkJoinTask<?>[] q; int s, m;
- if ((q = queue) != null) { // ignore if queue removed
- long u = (((s = queueTop) & (m = q.length - 1)) << ASHIFT) + ABASE;
- UNSAFE.putOrderedObject(q, u, t);
- queueTop = s + 1; // or use putOrderedInt
- if ((s -= queueBase) <= 2)
- pool.signalWork();
- else if (s == m)
- growQueue();
- }
- }
-
- /**
- * Creates or doubles queue array. Transfers elements by
- * emulating steals (deqs) from old array and placing, oldest
- * first, into new array.
- */
- private void growQueue() {
- ForkJoinTask<?>[] oldQ = queue;
- int size = oldQ != null ? oldQ.length << 1 : INITIAL_QUEUE_CAPACITY;
- if (size > MAXIMUM_QUEUE_CAPACITY)
- throw new RejectedExecutionException("Queue capacity exceeded");
- if (size < INITIAL_QUEUE_CAPACITY)
- size = INITIAL_QUEUE_CAPACITY;
- ForkJoinTask<?>[] q = queue = new ForkJoinTask<?>[size];
- int mask = size - 1;
- int top = queueTop;
- int oldMask;
- if (oldQ != null && (oldMask = oldQ.length - 1) >= 0) {
- for (int b = queueBase; b != top; ++b) {
- long u = ((b & oldMask) << ASHIFT) + ABASE;
- Object x = UNSAFE.getObjectVolatile(oldQ, u);
- if (x != null && UNSAFE.compareAndSwapObject(oldQ, u, x, null))
- UNSAFE.putObjectVolatile
- (q, ((b & mask) << ASHIFT) + ABASE, x);
+ try {
+ onTermination(exception);
+ } catch (Throwable ex) {
+ if (exception == null)
+ exception = ex;
+ } finally {
+ pool.deregisterWorker(this, exception);
}
}
}
-
- /**
- * Tries to take a task from the base of the queue, failing if
- * empty or contended. Note: Specializations of this code appear
- * in locallyDeqTask and elsewhere.
- *
- * @return a task, or null if none or contended
- */
- final ForkJoinTask<?> deqTask() {
- ForkJoinTask<?> t; ForkJoinTask<?>[] q; int b, i;
- if (queueTop != (b = queueBase) &&
- (q = queue) != null && // must read q after b
- (i = (q.length - 1) & b) >= 0 &&
- (t = q[i]) != null && queueBase == b &&
- UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE, t, null)) {
- queueBase = b + 1;
- return t;
- }
- return null;
- }
-
- /**
- * Tries to take a task from the base of own queue. Called only
- * by this thread.
- *
- * @return a task, or null if none
- */
- final ForkJoinTask<?> locallyDeqTask() {
- ForkJoinTask<?> t; int m, b, i;
- ForkJoinTask<?>[] q = queue;
- if (q != null && (m = q.length - 1) >= 0) {
- while (queueTop != (b = queueBase)) {
- if ((t = q[i = m & b]) != null &&
- queueBase == b &&
- UNSAFE.compareAndSwapObject(q, (i << ASHIFT) + ABASE,
- t, null)) {
- queueBase = b + 1;
- return t;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns a popped task, or null if empty.
- * Called only by this thread.
- */
- private ForkJoinTask<?> popTask() {
- int m;
- ForkJoinTask<?>[] q = queue;
- if (q != null && (m = q.length - 1) >= 0) {
- for (int s; (s = queueTop) != queueBase;) {
- int i = m & --s;
- long u = (i << ASHIFT) + ABASE; // raw offset
- ForkJoinTask<?> t = q[i];
- if (t == null) // lost to stealer
- break;
- if (UNSAFE.compareAndSwapObject(q, u, t, null)) {
- queueTop = s; // or putOrderedInt
- return t;
- }
- }
- }
- return null;
- }
-
- /**
- * Specialized version of popTask to pop only if topmost element
- * is the given task. Called only by this thread.
- *
- * @param t the task. Caller must ensure non-null.
- */
- final boolean unpushTask(ForkJoinTask<?> t) {
- ForkJoinTask<?>[] q;
- int s;
- if ((q = queue) != null && (s = queueTop) != queueBase &&
- UNSAFE.compareAndSwapObject
- (q, (((q.length - 1) & --s) << ASHIFT) + ABASE, t, null)) {
- queueTop = s; // or putOrderedInt
- return true;
- }
- return false;
- }
-
- /**
- * Returns next task, or null if empty or contended.
- */
- final ForkJoinTask<?> peekTask() {
- int m;
- ForkJoinTask<?>[] q = queue;
- if (q == null || (m = q.length - 1) < 0)
- return null;
- int i = locallyFifo ? queueBase : (queueTop - 1);
- return q[i & m];
- }
-
- // Support methods for ForkJoinPool
-
- /**
- * Runs the given task, plus any local tasks until queue is empty
- */
- final void execTask(ForkJoinTask<?> t) {
- currentSteal = t;
- for (;;) {
- if (t != null)
- t.doExec();
- if (queueTop == queueBase)
- break;
- t = locallyFifo ? locallyDeqTask() : popTask();
- }
- ++stealCount;
- currentSteal = null;
- }
-
- /**
- * Removes and cancels all tasks in queue. Can be called from any
- * thread.
- */
- final void cancelTasks() {
- ForkJoinTask<?> cj = currentJoin; // try to cancel ongoing tasks
- if (cj != null && cj.status >= 0)
- cj.cancelIgnoringExceptions();
- ForkJoinTask<?> cs = currentSteal;
- if (cs != null && cs.status >= 0)
- cs.cancelIgnoringExceptions();
- while (queueBase != queueTop) {
- ForkJoinTask<?> t = deqTask();
- if (t != null)
- t.cancelIgnoringExceptions();
- }
- }
-
- /**
- * Drains tasks to given collection c.
- *
- * @return the number of tasks drained
- */
- final int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
- int n = 0;
- while (queueBase != queueTop) {
- ForkJoinTask<?> t = deqTask();
- if (t != null) {
- c.add(t);
- ++n;
- }
- }
- return n;
- }
-
- // Support methods for ForkJoinTask
-
- /**
- * Returns an estimate of the number of tasks in the queue.
- */
- final int getQueueSize() {
- return queueTop - queueBase;
- }
-
- /**
- * Gets and removes a local task.
- *
- * @return a task, if available
- */
- final ForkJoinTask<?> pollLocalTask() {
- return locallyFifo ? locallyDeqTask() : popTask();
- }
-
- /**
- * Gets and removes a local or stolen task.
- *
- * @return a task, if available
- */
- final ForkJoinTask<?> pollTask() {
- ForkJoinWorkerThread[] ws;
- ForkJoinTask<?> t = pollLocalTask();
- if (t != null || (ws = pool.workers) == null)
- return t;
- int n = ws.length; // cheap version of FJP.scan
- int steps = n << 1;
- int r = nextSeed();
- int i = 0;
- while (i < steps) {
- ForkJoinWorkerThread w = ws[(i++ + r) & (n - 1)];
- if (w != null && w.queueBase != w.queueTop && w.queue != null) {
- if ((t = w.deqTask()) != null)
- return t;
- i = 0;
- }
- }
- return null;
- }
-
- /**
- * The maximum stolen->joining link depth allowed in helpJoinTask,
- * as well as the maximum number of retries (allowing on average
- * one staleness retry per level) per attempt to instead try
- * compensation. Depths for legitimate chains are unbounded, but
- * we use a fixed constant to avoid (otherwise unchecked) cycles
- * and bound staleness of traversal parameters at the expense of
- * sometimes blocking when we could be helping.
- */
- private static final int MAX_HELP = 16;
-
- /**
- * Possibly runs some tasks and/or blocks, until joinMe is done.
- *
- * @param joinMe the task to join
- * @return completion status on exit
- */
- final int joinTask(ForkJoinTask<?> joinMe) {
- ForkJoinTask<?> prevJoin = currentJoin;
- currentJoin = joinMe;
- for (int s, retries = MAX_HELP;;) {
- if ((s = joinMe.status) < 0) {
- currentJoin = prevJoin;
- return s;
- }
- if (retries > 0) {
- if (queueTop != queueBase) {
- if (!localHelpJoinTask(joinMe))
- retries = 0; // cannot help
- }
- else if (retries == MAX_HELP >>> 1) {
- --retries; // check uncommon case
- if (tryDeqAndExec(joinMe) >= 0)
- Thread.yield(); // for politeness
- }
- else
- retries = helpJoinTask(joinMe) ? MAX_HELP : retries - 1;
- }
- else {
- retries = MAX_HELP; // restart if not done
- pool.tryAwaitJoin(joinMe);
- }
- }
- }
-
- /**
- * If present, pops and executes the given task, or any other
- * cancelled task
- *
- * @return false if any other non-cancelled task exists in local queue
- */
- private boolean localHelpJoinTask(ForkJoinTask<?> joinMe) {
- int s, i; ForkJoinTask<?>[] q; ForkJoinTask<?> t;
- if ((s = queueTop) != queueBase && (q = queue) != null &&
- (i = (q.length - 1) & --s) >= 0 &&
- (t = q[i]) != null) {
- if (t != joinMe && t.status >= 0)
- return false;
- if (UNSAFE.compareAndSwapObject
- (q, (i << ASHIFT) + ABASE, t, null)) {
- queueTop = s; // or putOrderedInt
- t.doExec();
- }
- }
- return true;
- }
-
- /**
- * Tries to locate and execute tasks for a stealer of the given
- * task, or in turn one of its stealers, Traces
- * currentSteal->currentJoin links looking for a thread working on
- * a descendant of the given task and with a non-empty queue to
- * steal back and execute tasks from. The implementation is very
- * branchy to cope with potential inconsistencies or loops
- * encountering chains that are stale, unknown, or of length
- * greater than MAX_HELP links. All of these cases are dealt with
- * by just retrying by caller.
- *
- * @param joinMe the task to join
- * @return true if ran a task
- */
- private boolean helpJoinTask(ForkJoinTask<?> joinMe) {
- boolean helped = false;
- int m = pool.scanGuard & SMASK;
- ForkJoinWorkerThread[] ws = pool.workers;
- if (ws != null && ws.length > m && joinMe.status >= 0) {
- int levels = MAX_HELP; // remaining chain length
- ForkJoinTask<?> task = joinMe; // base of chain
- outer:for (ForkJoinWorkerThread thread = this;;) {
- // Try to find v, the stealer of task, by first using hint
- ForkJoinWorkerThread v = ws[thread.stealHint & m];
- if (v == null || v.currentSteal != task) {
- for (int j = 0; ;) { // search array
- if ((v = ws[j]) != null && v.currentSteal == task) {
- thread.stealHint = j;
- break; // save hint for next time
- }
- if (++j > m)
- break outer; // can't find stealer
- }
- }
- // Try to help v, using specialized form of deqTask
- for (;;) {
- ForkJoinTask<?>[] q; int b, i;
- if (joinMe.status < 0)
- break outer;
- if ((b = v.queueBase) == v.queueTop ||
- (q = v.queue) == null ||
- (i = (q.length-1) & b) < 0)
- break; // empty
- long u = (i << ASHIFT) + ABASE;
- ForkJoinTask<?> t = q[i];
- if (task.status < 0)
- break outer; // stale
- if (t != null && v.queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- v.queueBase = b + 1;
- v.stealHint = poolIndex;
- ForkJoinTask<?> ps = currentSteal;
- currentSteal = t;
- t.doExec();
- currentSteal = ps;
- helped = true;
- }
- }
- // Try to descend to find v's stealer
- ForkJoinTask<?> next = v.currentJoin;
- if (--levels > 0 && task.status >= 0 &&
- next != null && next != task) {
- task = next;
- thread = v;
- }
- else
- break; // max levels, stale, dead-end, or cyclic
- }
- }
- return helped;
- }
-
- /**
- * Performs an uncommon case for joinTask: If task t is at base of
- * some workers queue, steals and executes it.
- *
- * @param t the task
- * @return t's status
- */
- private int tryDeqAndExec(ForkJoinTask<?> t) {
- int m = pool.scanGuard & SMASK;
- ForkJoinWorkerThread[] ws = pool.workers;
- if (ws != null && ws.length > m && t.status >= 0) {
- for (int j = 0; j <= m; ++j) {
- ForkJoinTask<?>[] q; int b, i;
- ForkJoinWorkerThread v = ws[j];
- if (v != null &&
- (b = v.queueBase) != v.queueTop &&
- (q = v.queue) != null &&
- (i = (q.length - 1) & b) >= 0 &&
- q[i] == t) {
- long u = (i << ASHIFT) + ABASE;
- if (v.queueBase == b &&
- UNSAFE.compareAndSwapObject(q, u, t, null)) {
- v.queueBase = b + 1;
- v.stealHint = poolIndex;
- ForkJoinTask<?> ps = currentSteal;
- currentSteal = t;
- t.doExec();
- currentSteal = ps;
- }
- break;
- }
- }
- }
- return t.status;
- }
-
- /**
- * Implements ForkJoinTask.getSurplusQueuedTaskCount(). Returns
- * an estimate of the number of tasks, offset by a function of
- * number of idle workers.
- *
- * This method provides a cheap heuristic guide for task
- * partitioning when programmers, frameworks, tools, or languages
- * have little or no idea about task granularity. In essence by
- * offering this method, we ask users only about tradeoffs in
- * overhead vs expected throughput and its variance, rather than
- * how finely to partition tasks.
- *
- * In a steady state strict (tree-structured) computation, each
- * thread makes available for stealing enough tasks for other
- * threads to remain active. Inductively, if all threads play by
- * the same rules, each thread should make available only a
- * constant number of tasks.
- *
- * The minimum useful constant is just 1. But using a value of 1
- * would require immediate replenishment upon each steal to
- * maintain enough tasks, which is infeasible. Further,
- * partitionings/granularities of offered tasks should minimize
- * steal rates, which in general means that threads nearer the top
- * of computation tree should generate more than those nearer the
- * bottom. In perfect steady state, each thread is at
- * approximately the same level of computation tree. However,
- * producing extra tasks amortizes the uncertainty of progress and
- * diffusion assumptions.
- *
- * So, users will want to use values larger, but not much larger
- * than 1 to both smooth over transient shortages and hedge
- * against uneven progress; as traded off against the cost of
- * extra task overhead. We leave the user to pick a threshold
- * value to compare with the results of this call to guide
- * decisions, but recommend values such as 3.
- *
- * When all threads are active, it is on average OK to estimate
- * surplus strictly locally. In steady-state, if one thread is
- * maintaining say 2 surplus tasks, then so are others. So we can
- * just use estimated queue length (although note that (queueTop -
- * queueBase) can be an overestimate because of stealers lagging
- * increments of queueBase). However, this strategy alone leads
- * to serious mis-estimates in some non-steady-state conditions
- * (ramp-up, ramp-down, other stalls). We can detect many of these
- * by further considering the number of "idle" threads, that are
- * known to have zero queued tasks, so compensate by a factor of
- * (#idle/#active) threads.
- */
- final int getEstimatedSurplusTaskCount() {
- return queueTop - queueBase - pool.idlePerActive();
- }
-
- /**
- * Runs tasks until {@code pool.isQuiescent()}. We piggyback on
- * pool's active count ctl maintenance, but rather than blocking
- * when tasks cannot be found, we rescan until all others cannot
- * find tasks either. The bracketing by pool quiescerCounts
- * updates suppresses pool auto-shutdown mechanics that could
- * otherwise prematurely terminate the pool because all threads
- * appear to be inactive.
- */
- final void helpQuiescePool() {
- boolean active = true;
- ForkJoinTask<?> ps = currentSteal; // to restore below
- ForkJoinPool p = pool;
- p.addQuiescerCount(1);
- for (;;) {
- ForkJoinWorkerThread[] ws = p.workers;
- ForkJoinWorkerThread v = null;
- int n;
- if (queueTop != queueBase)
- v = this;
- else if (ws != null && (n = ws.length) > 1) {
- ForkJoinWorkerThread w;
- int r = nextSeed(); // cheap version of FJP.scan
- int steps = n << 1;
- for (int i = 0; i < steps; ++i) {
- if ((w = ws[(i + r) & (n - 1)]) != null &&
- w.queueBase != w.queueTop) {
- v = w;
- break;
- }
- }
- }
- if (v != null) {
- ForkJoinTask<?> t;
- if (!active) {
- active = true;
- p.addActiveCount(1);
- }
- if ((t = (v != this) ? v.deqTask() :
- locallyFifo ? locallyDeqTask() : popTask()) != null) {
- currentSteal = t;
- t.doExec();
- currentSteal = ps;
- }
- }
- else {
- if (active) {
- active = false;
- p.addActiveCount(-1);
- }
- if (p.isQuiescent()) {
- p.addActiveCount(1);
- p.addQuiescerCount(-1);
- break;
- }
- }
- }
- }
-
- // Unsafe mechanics
- private static final sun.misc.Unsafe UNSAFE;
- private static final long ABASE;
- private static final int ASHIFT;
-
- static {
- int s;
- try {
- UNSAFE = sun.misc.Unsafe.getUnsafe();
- Class<?> a = ForkJoinTask[].class;
- ABASE = UNSAFE.arrayBaseOffset(a);
- s = UNSAFE.arrayIndexScale(a);
- } catch (Exception e) {
- throw new Error(e);
- }
- if ((s & (s-1)) != 0)
- throw new Error("data type scale not a power of two");
- ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
- }
-
}
diff --git a/luni/src/main/java/java/util/concurrent/Future.java b/luni/src/main/java/java/util/concurrent/Future.java
index 6a37729..32e8145 100644
--- a/luni/src/main/java/java/util/concurrent/Future.java
+++ b/luni/src/main/java/java/util/concurrent/Future.java
@@ -7,19 +7,19 @@
package java.util.concurrent;
/**
- * A <tt>Future</tt> represents the result of an asynchronous
+ * A {@code Future} represents the result of an asynchronous
* computation. Methods are provided to check if the computation is
* complete, to wait for its completion, and to retrieve the result of
* the computation. The result can only be retrieved using method
- * <tt>get</tt> when the computation has completed, blocking if
+ * {@code get} when the computation has completed, blocking if
* necessary until it is ready. Cancellation is performed by the
- * <tt>cancel</tt> method. Additional methods are provided to
+ * {@code cancel} method. Additional methods are provided to
* determine if the task completed normally or was cancelled. Once a
* computation has completed, the computation cannot be cancelled.
- * If you would like to use a <tt>Future</tt> for the sake
+ * If you would like to use a {@code Future} for the sake
* of cancellability but not provide a usable result, you can
* declare types of the form {@code Future<?>} and
- * return <tt>null</tt> as a result of the underlying task.
+ * return {@code null} as a result of the underlying task.
*
* <p>
* <b>Sample Usage</b> (Note that the following classes are all
@@ -43,16 +43,16 @@
* }
* }}</pre>
*
- * The {@link FutureTask} class is an implementation of <tt>Future</tt> that
- * implements <tt>Runnable</tt>, and so may be executed by an <tt>Executor</tt>.
- * For example, the above construction with <tt>submit</tt> could be replaced by:
+ * The {@link FutureTask} class is an implementation of {@code Future} that
+ * implements {@code Runnable}, and so may be executed by an {@code Executor}.
+ * For example, the above construction with {@code submit} could be replaced by:
* <pre> {@code
- * FutureTask<String> future =
- * new FutureTask<String>(new Callable<String>() {
- * public String call() {
- * return searcher.search(target);
- * }});
- * executor.execute(future);}</pre>
+ * FutureTask<String> future =
+ * new FutureTask<String>(new Callable<String>() {
+ * public String call() {
+ * return searcher.search(target);
+ * }});
+ * executor.execute(future);}</pre>
*
* <p>Memory consistency effects: Actions taken by the asynchronous computation
* <a href="package-summary.html#MemoryVisibility"> <i>happen-before</i></a>
@@ -62,7 +62,7 @@
* @see Executor
* @since 1.5
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface Future<V> {
@@ -70,41 +70,41 @@
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
- * and this task has not started when <tt>cancel</tt> is called,
+ * and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
- * then the <tt>mayInterruptIfRunning</tt> parameter determines
+ * then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
- * always return <tt>true</tt>. Subsequent calls to {@link #isCancelled}
- * will always return <tt>true</tt> if this method returned <tt>true</tt>.
+ * always return {@code true}. Subsequent calls to {@link #isCancelled}
+ * will always return {@code true} if this method returned {@code true}.
*
- * @param mayInterruptIfRunning <tt>true</tt> if the thread executing this
+ * @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
- * @return <tt>false</tt> if the task could not be cancelled,
+ * @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
- * <tt>true</tt> otherwise
+ * {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
/**
- * Returns <tt>true</tt> if this task was cancelled before it completed
+ * Returns {@code true} if this task was cancelled before it completed
* normally.
*
- * @return <tt>true</tt> if this task was cancelled before it completed
+ * @return {@code true} if this task was cancelled before it completed
*/
boolean isCancelled();
/**
- * Returns <tt>true</tt> if this task completed.
+ * Returns {@code true} if this task completed.
*
* Completion may be due to normal termination, an exception, or
* cancellation -- in all of these cases, this method will return
- * <tt>true</tt>.
+ * {@code true}.
*
- * @return <tt>true</tt> if this task completed
+ * @return {@code true} if this task completed
*/
boolean isDone();
diff --git a/luni/src/main/java/java/util/concurrent/FutureTask.java b/luni/src/main/java/java/util/concurrent/FutureTask.java
index d51881d..114fe49 100644
--- a/luni/src/main/java/java/util/concurrent/FutureTask.java
+++ b/luni/src/main/java/java/util/concurrent/FutureTask.java
@@ -83,12 +83,11 @@
*
* @param s completed state value
*/
+ @SuppressWarnings("unchecked")
private V report(int s) throws ExecutionException {
Object x = outcome;
- if (s == NORMAL) {
- @SuppressWarnings("unchecked") V v = (V)x;
- return v;
- }
+ if (s == NORMAL)
+ return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
@@ -134,19 +133,23 @@
}
public boolean cancel(boolean mayInterruptIfRunning) {
- if (state != NEW)
+ if (!(state == NEW &&
+ UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
+ mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
- if (mayInterruptIfRunning) {
- if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, INTERRUPTING))
- return false;
- Thread t = runner;
- if (t != null)
- t.interrupt();
- UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // final state
+ try { // in case call to interrupt throws exception
+ if (mayInterruptIfRunning) {
+ try {
+ Thread t = runner;
+ if (t != null)
+ t.interrupt();
+ } finally { // final state
+ UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
+ }
+ }
+ } finally {
+ finishCompletion();
}
- else if (!UNSAFE.compareAndSwapInt(this, stateOffset, NEW, CANCELLED))
- return false;
- finishCompletion();
return true;
}
@@ -363,7 +366,7 @@
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
- long last = timed ? System.nanoTime() : 0L;
+ final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
@@ -378,18 +381,19 @@
q.thread = null;
return s;
}
+ else if (s == COMPLETING) // cannot time out yet
+ Thread.yield();
else if (q == null)
q = new WaitNode();
else if (!queued)
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
- long now = System.nanoTime();
- if ((nanos -= (now - last)) <= 0L) {
+ nanos = deadline - System.nanoTime();
+ if (nanos <= 0L) {
removeWaiter(q);
return state;
}
- last = now;
LockSupport.parkNanos(this, nanos);
}
else
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
index 6f32c47..64b0bf1 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingDeque.java
@@ -21,7 +21,7 @@
* An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
* linked nodes.
*
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
* way to prevent excessive expansion. The capacity, if unspecified,
* is equal to {@link Integer#MAX_VALUE}. Linked nodes are
* dynamically created upon each insertion unless this would bring the
@@ -44,7 +44,7 @@
*/
public class LinkedBlockingDeque<E>
extends AbstractQueue<E>
- implements BlockingDeque<E>, java.io.Serializable {
+ implements BlockingDeque<E>, java.io.Serializable {
/*
* Implemented as a simple doubly-linked list protected by a
@@ -1123,11 +1123,10 @@
}
/**
- * Saves the state of this deque to a stream (that is, serializes it).
+ * Saves this deque to a stream (that is, serializes it).
*
* @serialData The capacity (int), followed by elements (each an
* {@code Object}) in the proper order, followed by a null
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1148,8 +1147,6 @@
/**
* Reconstitutes this deque from a stream (that is, deserializes it).
- *
- * @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
index e8c9edb..0719828 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedBlockingQueue.java
@@ -31,7 +31,7 @@
* Linked queues typically have higher throughput than array-based queues but
* less predictable performance in most concurrent applications.
*
- * <p> The optional capacity bound constructor argument serves as a
+ * <p>The optional capacity bound constructor argument serves as a
* way to prevent excessive queue expansion. The capacity, if unspecified,
* is equal to {@link Integer#MAX_VALUE}. Linked nodes are
* dynamically created upon each insertion unless this would bring the
@@ -44,7 +44,6 @@
* @since 1.5
* @author Doug Lea
* @param <E> the type of elements held in this collection
- *
*/
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
@@ -188,7 +187,7 @@
}
/**
- * Lock to prevent both puts and takes.
+ * Locks to prevent both puts and takes.
*/
void fullyLock() {
putLock.lock();
@@ -196,7 +195,7 @@
}
/**
- * Unlock to allow both puts and takes.
+ * Unlocks to allow both puts and takes.
*/
void fullyUnlock() {
takeLock.unlock();
@@ -262,7 +261,6 @@
}
}
-
// this doc comment is overridden to remove the reference to collections
// greater in size than Integer.MAX_VALUE
/**
@@ -335,7 +333,7 @@
* necessary up to the specified wait time for space to become available.
*
* @return {@code true} if successful, or {@code false} if
- * the specified waiting time elapses before space is available.
+ * the specified waiting time elapses before space is available
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
@@ -401,7 +399,6 @@
return c >= 0;
}
-
public E take() throws InterruptedException {
E x;
int c = -1;
@@ -756,6 +753,7 @@
* item to hand out so that if hasNext() reports true, we will
* still have it to return even if lost race with a take etc.
*/
+
private Node<E> current;
private Node<E> lastRet;
private E currentElement;
@@ -830,12 +828,11 @@
}
/**
- * Saves the state to a stream (that is, serializes it).
+ * Saves this queue to a stream (that is, serializes it).
*
* @serialData The capacity is emitted (int), followed by all of
* its elements (each an {@code Object}) in the proper order,
* followed by a null
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -858,8 +855,6 @@
/**
* Reconstitutes this queue from a stream (that is, deserializes it).
- *
- * @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
index 2a3446e..cff5dbf 100644
--- a/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
+++ b/luni/src/main/java/java/util/concurrent/LinkedTransferQueue.java
@@ -667,7 +667,7 @@
* @return matched item, or e if unmatched on interrupt or timeout
*/
private E awaitMatch(Node s, Node pred, E e, boolean timed, long nanos) {
- long lastTime = timed ? System.nanoTime() : 0L;
+ final long deadline = timed ? System.nanoTime() + nanos : 0L;
Thread w = Thread.currentThread();
int spins = -1; // initialized after first item and cancel checks
ThreadLocalRandom randomYields = null; // bound if needed
@@ -698,10 +698,9 @@
s.waiter = w; // request unpark then recheck
}
else if (timed) {
- long now = System.nanoTime();
- if ((nanos -= now - lastTime) > 0)
+ nanos = deadline - System.nanoTime();
+ if (nanos > 0L)
LockSupport.parkNanos(this, nanos);
- lastTime = now;
}
else {
LockSupport.park(this);
@@ -980,7 +979,6 @@
return false;
}
-
/**
* Creates an initially empty {@code LinkedTransferQueue}.
*/
@@ -1267,11 +1265,10 @@
}
/**
- * Saves the state to a stream (that is, serializes it).
+ * Saves this queue to a stream (that is, serializes it).
*
* @serialData All of the elements (each an {@code E}) in
* the proper order, followed by a null
- * @param s the stream
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1283,16 +1280,14 @@
}
/**
- * Reconstitutes the Queue instance from a stream (that is,
- * deserializes it).
- *
- * @param s the stream
+ * Reconstitutes this queue from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
for (;;) {
- @SuppressWarnings("unchecked") E item = (E) s.readObject();
+ @SuppressWarnings("unchecked")
+ E item = (E) s.readObject();
if (item == null)
break;
else
diff --git a/luni/src/main/java/java/util/concurrent/Phaser.java b/luni/src/main/java/java/util/concurrent/Phaser.java
index 25ff743..a9adbe5 100644
--- a/luni/src/main/java/java/util/concurrent/Phaser.java
+++ b/luni/src/main/java/java/util/concurrent/Phaser.java
@@ -17,7 +17,7 @@
* {@link java.util.concurrent.CountDownLatch CountDownLatch}
* but supporting more flexible usage.
*
- * <p> <b>Registration.</b> Unlike the case for other barriers, the
+ * <p><b>Registration.</b> Unlike the case for other barriers, the
* number of parties <em>registered</em> to synchronize on a phaser
* may vary over time. Tasks may be registered at any time (using
* methods {@link #register}, {@link #bulkRegister}, or forms of
@@ -30,7 +30,7 @@
* (However, you can introduce such bookkeeping by subclassing this
* class.)
*
- * <p> <b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
+ * <p><b>Synchronization.</b> Like a {@code CyclicBarrier}, a {@code
* Phaser} may be repeatedly awaited. Method {@link
* #arriveAndAwaitAdvance} has effect analogous to {@link
* java.util.concurrent.CyclicBarrier#await CyclicBarrier.await}. Each
@@ -74,7 +74,7 @@
*
* </ul>
*
- * <p> <b>Termination.</b> A phaser may enter a <em>termination</em>
+ * <p><b>Termination.</b> A phaser may enter a <em>termination</em>
* state, that may be checked using method {@link #isTerminated}. Upon
* termination, all synchronization methods immediately return without
* waiting for advance, as indicated by a negative return value.
@@ -89,7 +89,7 @@
* also available to abruptly release waiting threads and allow them
* to terminate.
*
- * <p> <b>Tiering.</b> Phasers may be <em>tiered</em> (i.e.,
+ * <p><b>Tiering.</b> Phasers may be <em>tiered</em> (i.e.,
* constructed in tree structures) to reduce contention. Phasers with
* large numbers of parties that would otherwise experience heavy
* synchronization contention costs may instead be set up so that
@@ -1065,7 +1065,7 @@
final boolean timed;
boolean wasInterrupted;
long nanos;
- long lastTime;
+ final long deadline;
volatile Thread thread; // nulled to cancel wait
QNode next;
@@ -1076,7 +1076,7 @@
this.interruptible = interruptible;
this.nanos = nanos;
this.timed = timed;
- this.lastTime = timed ? System.nanoTime() : 0L;
+ this.deadline = timed ? System.nanoTime() + nanos : 0L;
thread = Thread.currentThread();
}
@@ -1095,9 +1095,7 @@
}
if (timed) {
if (nanos > 0L) {
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
+ nanos = deadline - System.nanoTime();
}
if (nanos <= 0L) {
thread = null;
@@ -1112,7 +1110,7 @@
return true;
else if (!timed)
LockSupport.park(this);
- else if (nanos > 0)
+ else if (nanos > 0L)
LockSupport.parkNanos(this, nanos);
return isReleasable();
}
diff --git a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
index 26c72eb..0f9e715 100644
--- a/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
+++ b/luni/src/main/java/java/util/concurrent/PriorityBlockingQueue.java
@@ -6,7 +6,8 @@
package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.*;
// BEGIN android-note
@@ -65,6 +66,7 @@
* @author Doug Lea
* @param <E> the type of elements held in this collection
*/
+@SuppressWarnings("unchecked")
public class PriorityBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = 5595510919245408276L;
@@ -311,7 +313,6 @@
* @param k the position to fill
* @param x the item to insert
* @param array the heap array
- * @param n heap size
*/
private static <T> void siftUpComparable(int k, T x, Object[] array) {
Comparable<? super T> key = (Comparable<? super T>) x;
@@ -351,39 +352,43 @@
*/
private static <T> void siftDownComparable(int k, T x, Object[] array,
int n) {
- Comparable<? super T> key = (Comparable<? super T>)x;
- int half = n >>> 1; // loop while a non-leaf
- while (k < half) {
- int child = (k << 1) + 1; // assume left child is least
- Object c = array[child];
- int right = child + 1;
- if (right < n &&
- ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
- c = array[child = right];
- if (key.compareTo((T) c) <= 0)
- break;
- array[k] = c;
- k = child;
+ if (n > 0) {
+ Comparable<? super T> key = (Comparable<? super T>)x;
+ int half = n >>> 1; // loop while a non-leaf
+ while (k < half) {
+ int child = (k << 1) + 1; // assume left child is least
+ Object c = array[child];
+ int right = child + 1;
+ if (right < n &&
+ ((Comparable<? super T>) c).compareTo((T) array[right]) > 0)
+ c = array[child = right];
+ if (key.compareTo((T) c) <= 0)
+ break;
+ array[k] = c;
+ k = child;
+ }
+ array[k] = key;
}
- array[k] = key;
}
private static <T> void siftDownUsingComparator(int k, T x, Object[] array,
int n,
Comparator<? super T> cmp) {
- int half = n >>> 1;
- while (k < half) {
- int child = (k << 1) + 1;
- Object c = array[child];
- int right = child + 1;
- if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
- c = array[child = right];
- if (cmp.compare(x, (T) c) <= 0)
- break;
- array[k] = c;
- k = child;
+ if (n > 0) {
+ int half = n >>> 1;
+ while (k < half) {
+ int child = (k << 1) + 1;
+ Object c = array[child];
+ int right = child + 1;
+ if (right < n && cmp.compare((T) c, (T) array[right]) > 0)
+ c = array[child = right];
+ if (cmp.compare(x, (T) c) <= 0)
+ break;
+ array[k] = c;
+ k = child;
+ }
+ array[k] = x;
}
- array[k] = x;
}
/**
@@ -866,10 +871,11 @@
}
/**
- * Saves the state to a stream (that is, serializes it). For
- * compatibility with previous version of this class,
- * elements are first copied to a java.util.PriorityQueue,
- * which is then serialized.
+ * Saves this queue to a stream (that is, serializes it).
+ *
+ * For compatibility with previous version of this class, elements
+ * are first copied to a java.util.PriorityQueue, which is then
+ * serialized.
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -886,10 +892,7 @@
}
/**
- * Reconstitutes the {@code PriorityBlockingQueue} instance from a stream
- * (that is, deserializes it).
- *
- * @param s the stream
+ * Reconstitutes this queue from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveAction.java b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
index 48066c9..8d666f6 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveAction.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveAction.java
@@ -34,7 +34,7 @@
* }
* }
* // implementation details follow:
- * final static int THRESHOLD = 1000;
+ * static final int THRESHOLD = 1000;
* void sortSequentially(int lo, int hi) {
* Arrays.sort(array, lo, hi);
* }
@@ -111,21 +111,21 @@
* int h = hi;
* Applyer right = null;
* while (h - l > 1 && getSurplusQueuedTaskCount() <= 3) {
- * int mid = (l + h) >>> 1;
- * right = new Applyer(array, mid, h, right);
- * right.fork();
- * h = mid;
+ * int mid = (l + h) >>> 1;
+ * right = new Applyer(array, mid, h, right);
+ * right.fork();
+ * h = mid;
* }
* double sum = atLeaf(l, h);
* while (right != null) {
- * if (right.tryUnfork()) // directly calculate if not stolen
- * sum += right.atLeaf(right.lo, right.hi);
+ * if (right.tryUnfork()) // directly calculate if not stolen
+ * sum += right.atLeaf(right.lo, right.hi);
* else {
- * right.join();
- * sum += right.result;
- * }
- * right = right.next;
- * }
+ * right.join();
+ * sum += right.result;
+ * }
+ * right = right.next;
+ * }
* result = sum;
* }
* }}</pre>
diff --git a/luni/src/main/java/java/util/concurrent/RecursiveTask.java b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
index 5e17280..421c9d3 100644
--- a/luni/src/main/java/java/util/concurrent/RecursiveTask.java
+++ b/luni/src/main/java/java/util/concurrent/RecursiveTask.java
@@ -17,7 +17,7 @@
* Fibonacci(int n) { this.n = n; }
* Integer compute() {
* if (n <= 1)
- * return n;
+ * return n;
* Fibonacci f1 = new Fibonacci(n - 1);
* f1.fork();
* Fibonacci f2 = new Fibonacci(n - 2);
diff --git a/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java b/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
index f0005d1..c61365f 100644
--- a/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
+++ b/luni/src/main/java/java/util/concurrent/RejectedExecutionException.java
@@ -17,14 +17,14 @@
private static final long serialVersionUID = -375805702767069545L;
/**
- * Constructs a <tt>RejectedExecutionException</tt> with no detail message.
+ * Constructs a {@code RejectedExecutionException} with no detail message.
* The cause is not initialized, and may subsequently be
* initialized by a call to {@link #initCause(Throwable) initCause}.
*/
public RejectedExecutionException() { }
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified detail message. The cause is not initialized, and may
* subsequently be initialized by a call to {@link
* #initCause(Throwable) initCause}.
@@ -36,7 +36,7 @@
}
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified detail message and cause.
*
* @param message the detail message
@@ -48,10 +48,10 @@
}
/**
- * Constructs a <tt>RejectedExecutionException</tt> with the
+ * Constructs a {@code RejectedExecutionException} with the
* specified cause. The detail message is set to {@code (cause ==
* null ? null : cause.toString())} (which typically contains
- * the class and detail message of <tt>cause</tt>).
+ * the class and detail message of {@code cause}).
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method)
diff --git a/luni/src/main/java/java/util/concurrent/RunnableFuture.java b/luni/src/main/java/java/util/concurrent/RunnableFuture.java
index 2d6d52c..ccd28e3 100644
--- a/luni/src/main/java/java/util/concurrent/RunnableFuture.java
+++ b/luni/src/main/java/java/util/concurrent/RunnableFuture.java
@@ -8,13 +8,13 @@
/**
* A {@link Future} that is {@link Runnable}. Successful execution of
- * the <tt>run</tt> method causes completion of the <tt>Future</tt>
+ * the {@code run} method causes completion of the {@code Future}
* and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
diff --git a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
index fbb995c..7125233 100644
--- a/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
+++ b/luni/src/main/java/java/util/concurrent/RunnableScheduledFuture.java
@@ -8,13 +8,13 @@
/**
* A {@link ScheduledFuture} that is {@link Runnable}. Successful
- * execution of the <tt>run</tt> method causes completion of the
- * <tt>Future</tt> and allows access to its results.
+ * execution of the {@code run} method causes completion of the
+ * {@code Future} and allows access to its results.
* @see FutureTask
* @see Executor
* @since 1.6
* @author Doug Lea
- * @param <V> The result type returned by this Future's <tt>get</tt> method
+ * @param <V> The result type returned by this Future's {@code get} method
*/
public interface RunnableScheduledFuture<V> extends RunnableFuture<V>, ScheduledFuture<V> {
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
index 71e57ed..b978fae 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledExecutorService.java
@@ -10,26 +10,26 @@
* An {@link ExecutorService} that can schedule commands to run after a given
* delay, or to execute periodically.
*
- * <p> The <tt>schedule</tt> methods create tasks with various delays
+ * <p>The {@code schedule} methods create tasks with various delays
* and return a task object that can be used to cancel or check
- * execution. The <tt>scheduleAtFixedRate</tt> and
- * <tt>scheduleWithFixedDelay</tt> methods create and execute tasks
+ * execution. The {@code scheduleAtFixedRate} and
+ * {@code scheduleWithFixedDelay} methods create and execute tasks
* that run periodically until cancelled.
*
- * <p> Commands submitted using the {@link Executor#execute} and
- * {@link ExecutorService} <tt>submit</tt> methods are scheduled with
+ * <p>Commands submitted using the {@link Executor#execute} and
+ * {@link ExecutorService} {@code submit} methods are scheduled with
* a requested delay of zero. Zero and negative delays (but not
- * periods) are also allowed in <tt>schedule</tt> methods, and are
+ * periods) are also allowed in {@code schedule} methods, and are
* treated as requests for immediate execution.
*
- * <p>All <tt>schedule</tt> methods accept <em>relative</em> delays and
+ * <p>All {@code schedule} methods accept <em>relative</em> delays and
* periods as arguments, not absolute times or dates. It is a simple
* matter to transform an absolute time represented as a {@link
* java.util.Date} to the required form. For example, to schedule at
- * a certain future <tt>date</tt>, you can use: <tt>schedule(task,
+ * a certain future {@code date}, you can use: {@code schedule(task,
* date.getTime() - System.currentTimeMillis(),
- * TimeUnit.MILLISECONDS)</tt>. Beware however that expiration of a
- * relative delay need not coincide with the current <tt>Date</tt> at
+ * TimeUnit.MILLISECONDS)}. Beware however that expiration of a
+ * relative delay need not coincide with the current {@code Date} at
* which the task is enabled due to network time synchronization
* protocols, clock drift, or other factors.
*
@@ -72,8 +72,8 @@
* @param delay the time from now to delay execution
* @param unit the time unit of the delay parameter
* @return a ScheduledFuture representing pending completion of
- * the task and whose <tt>get()</tt> method will return
- * <tt>null</tt> upon completion
+ * the task and whose {@code get()} method will return
+ * {@code null} upon completion
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
* @throws NullPointerException if command is null
@@ -100,8 +100,8 @@
* Creates and executes a periodic action that becomes enabled first
* after the given initial delay, and subsequently with the given
* period; that is executions will commence after
- * <tt>initialDelay</tt> then <tt>initialDelay+period</tt>, then
- * <tt>initialDelay + 2 * period</tt>, and so on.
+ * {@code initialDelay} then {@code initialDelay+period}, then
+ * {@code initialDelay + 2 * period}, and so on.
* If any execution of the task
* encounters an exception, subsequent executions are suppressed.
* Otherwise, the task will only terminate via cancellation or
@@ -114,7 +114,7 @@
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose <tt>get()</tt> method will throw an
+ * the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
@@ -141,7 +141,7 @@
* execution and the commencement of the next
* @param unit the time unit of the initialDelay and delay parameters
* @return a ScheduledFuture representing pending completion of
- * the task, and whose <tt>get()</tt> method will throw an
+ * the task, and whose {@code get()} method will throw an
* exception upon cancellation
* @throws RejectedExecutionException if the task cannot be
* scheduled for execution
diff --git a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
index e41f0c3..a52351b 100644
--- a/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ScheduledThreadPoolExecutor.java
@@ -13,7 +13,6 @@
// BEGIN android-note
// omit class-level docs on setRemoveOnCancelPolicy()
-// removed security manager docs
// END android-note
/**
@@ -31,7 +30,7 @@
* submission.
*
* <p>When a submitted task is cancelled before it is run, execution
- * is suppressed. Such a cancelled task is not
+ * is suppressed. By default, such a cancelled task is not
* automatically removed from the work queue until its delay
* elapses. While this enables further inspection and monitoring, it
* may also cause unbounded retention of cancelled tasks.
@@ -54,7 +53,7 @@
* without threads to handle tasks once they become eligible to run.
*
* <p><b>Extension notes:</b> This class overrides the
- * {@link ThreadPoolExecutor#execute execute} and
+ * {@link ThreadPoolExecutor#execute(Runnable) execute} and
* {@link AbstractExecutorService#submit(Runnable) submit}
* methods to generate internal {@link ScheduledFuture} objects to
* control per-task delays and scheduling. To preserve
@@ -196,7 +195,7 @@
}
/**
- * Creates a one-shot action with given nanoTime-based trigger.
+ * Creates a one-shot action with given nanoTime-based trigger time.
*/
ScheduledFutureTask(Callable<V> callable, long ns) {
super(callable);
@@ -224,15 +223,14 @@
else
return 1;
}
- long diff = (getDelay(NANOSECONDS) -
- other.getDelay(NANOSECONDS));
+ long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
}
/**
- * Returns true if this is a periodic (not a one-shot) action.
+ * Returns {@code true} if this is a periodic (not a one-shot) action.
*
- * @return true if periodic
+ * @return {@code true} if periodic
*/
public boolean isPeriodic() {
return period != 0;
@@ -289,7 +287,7 @@
* is shut down, rejects the task. Otherwise adds task to queue
* and starts a thread, if necessary, to run it. (We cannot
* prestart the thread to run the task because the task (probably)
- * shouldn't be run yet,) If the pool is shut down while the task
+ * shouldn't be run yet.) If the pool is shut down while the task
* is being added, cancel and remove it if required by state and
* run-after-shutdown parameters.
*
@@ -628,7 +626,7 @@
* {@code false} when already shutdown.
* This value is by default {@code false}.
*
- * @param value if {@code true}, continue after shutdown, else don't.
+ * @param value if {@code true}, continue after shutdown, else don't
* @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
*/
public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
@@ -660,7 +658,7 @@
* {@code false} when already shutdown.
* This value is by default {@code true}.
*
- * @param value if {@code true}, execute after shutdown, else don't.
+ * @param value if {@code true}, execute after shutdown, else don't
* @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
*/
public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
@@ -834,7 +832,7 @@
private final Condition available = lock.newCondition();
/**
- * Set f's heapIndex if it is a ScheduledFutureTask.
+ * Sets f's heapIndex if it is a ScheduledFutureTask.
*/
private void setIndex(RunnableScheduledFuture<?> f, int idx) {
if (f instanceof ScheduledFutureTask)
@@ -842,7 +840,7 @@
}
/**
- * Sift element added at bottom up to its heap-ordered spot.
+ * Sifts element added at bottom up to its heap-ordered spot.
* Call only when holding lock.
*/
private void siftUp(int k, RunnableScheduledFuture<?> key) {
@@ -860,7 +858,7 @@
}
/**
- * Sift element added at top down to its heap-ordered spot.
+ * Sifts element added at top down to its heap-ordered spot.
* Call only when holding lock.
*/
private void siftDown(int k, RunnableScheduledFuture<?> key) {
@@ -882,7 +880,7 @@
}
/**
- * Resize the heap array. Call only when holding lock.
+ * Resizes the heap array. Call only when holding lock.
*/
private void grow() {
int oldCapacity = queue.length;
@@ -893,7 +891,7 @@
}
/**
- * Find index of given object, or -1 if absent
+ * Finds index of given object, or -1 if absent.
*/
private int indexOf(Object x) {
if (x != null) {
@@ -1054,7 +1052,8 @@
long delay = first.getDelay(NANOSECONDS);
if (delay <= 0)
return finishPoll(first);
- else if (leader != null)
+ first = null; // don't retain ref while waiting
+ if (leader != null)
available.await();
else {
Thread thisThread = Thread.currentThread();
@@ -1094,6 +1093,7 @@
return finishPoll(first);
if (nanos <= 0)
return null;
+ first = null; // don't retain ref while waiting
if (nanos < delay || leader != null)
nanos = available.awaitNanos(nanos);
else {
@@ -1134,7 +1134,7 @@
}
/**
- * Return first element only if it is expired.
+ * Returns first element only if it is expired.
* Used only by drainTo. Call only when holding lock.
*/
private RunnableScheduledFuture<?> peekExpired() {
diff --git a/luni/src/main/java/java/util/concurrent/Semaphore.java b/luni/src/main/java/java/util/concurrent/Semaphore.java
index bf2524c..9ee18a8 100644
--- a/luni/src/main/java/java/util/concurrent/Semaphore.java
+++ b/luni/src/main/java/java/util/concurrent/Semaphore.java
@@ -5,8 +5,8 @@
*/
package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.locks.*;
+import java.util.Collection;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* A counting semaphore. Conceptually, a semaphore maintains a set of
@@ -79,13 +79,13 @@
* exclusion lock. This is more commonly known as a <em>binary
* semaphore</em>, because it only has two states: one permit
* available, or zero permits available. When used in this way, the
- * binary semaphore has the property (unlike many {@link Lock}
+ * binary semaphore has the property (unlike many {@link java.util.concurrent.locks.Lock}
* implementations), that the "lock" can be released by a
* thread other than the owner (as semaphores have no notion of
* ownership). This can be useful in some specialized contexts, such
* as deadlock recovery.
*
- * <p> The constructor for this class optionally accepts a
+ * <p>The constructor for this class optionally accepts a
* <em>fairness</em> parameter. When set false, this class makes no
* guarantees about the order in which threads acquire permits. In
* particular, <em>barging</em> is permitted, that is, a thread
@@ -123,9 +123,7 @@
*
* @since 1.5
* @author Doug Lea
- *
*/
-
public class Semaphore implements java.io.Serializable {
private static final long serialVersionUID = -3222578661600680210L;
/** All mechanics via AbstractQueuedSynchronizer subclass */
@@ -461,7 +459,6 @@
*
* @param permits the number of permits to acquire
* @throws IllegalArgumentException if {@code permits} is negative
- *
*/
public void acquireUninterruptibly(int permits) {
if (permits < 0) throw new IllegalArgumentException();
diff --git a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
index b05ae0a..ea6b3d1 100644
--- a/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
+++ b/luni/src/main/java/java/util/concurrent/SynchronousQueue.java
@@ -6,7 +6,8 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.*;
+import java.util.concurrent.locks.LockSupport;
+import java.util.concurrent.locks.ReentrantLock;
import java.util.*;
// BEGIN android-note
@@ -18,17 +19,17 @@
* operation must wait for a corresponding remove operation by another
* thread, and vice versa. A synchronous queue does not have any
* internal capacity, not even a capacity of one. You cannot
- * <tt>peek</tt> at a synchronous queue because an element is only
+ * {@code peek} at a synchronous queue because an element is only
* present when you try to remove it; you cannot insert an element
* (using any method) unless another thread is trying to remove it;
* you cannot iterate as there is nothing to iterate. The
* <em>head</em> of the queue is the element that the first queued
* inserting thread is trying to add to the queue; if there is no such
* queued thread then no element is available for removal and
- * <tt>poll()</tt> will return <tt>null</tt>. For purposes of other
- * <tt>Collection</tt> methods (for example <tt>contains</tt>), a
- * <tt>SynchronousQueue</tt> acts as an empty collection. This queue
- * does not permit <tt>null</tt> elements.
+ * {@code poll()} will return {@code null}. For purposes of other
+ * {@code Collection} methods (for example {@code contains}), a
+ * {@code SynchronousQueue} acts as an empty collection. This queue
+ * does not permit {@code null} elements.
*
* <p>Synchronous queues are similar to rendezvous channels used in
* CSP and Ada. They are well suited for handoff designs, in which an
@@ -36,10 +37,10 @@
* in another thread in order to hand it some information, event, or
* task.
*
- * <p> This class supports an optional fairness policy for ordering
+ * <p>This class supports an optional fairness policy for ordering
* waiting producer and consumer threads. By default, this ordering
* is not guaranteed. However, a queue constructed with fairness set
- * to <tt>true</tt> grants threads access in FIFO order.
+ * to {@code true} grants threads access in FIFO order.
*
* <p>This class and its iterator implement all of the
* <em>optional</em> methods of the {@link Collection} and {@link
@@ -133,7 +134,7 @@
/**
* Shared internal API for dual stacks and queues.
*/
- abstract static class Transferer {
+ abstract static class Transferer<E> {
/**
* Performs a put or take.
*
@@ -147,7 +148,7 @@
* the caller can distinguish which of these occurred
* by checking Thread.interrupted.
*/
- abstract Object transfer(Object e, boolean timed, long nanos);
+ abstract E transfer(E e, boolean timed, long nanos);
}
/** The number of CPUs, for spin control */
@@ -176,7 +177,7 @@
static final long spinForTimeoutThreshold = 1000L;
/** Dual stack */
- static final class TransferStack extends Transferer {
+ static final class TransferStack<E> extends Transferer<E> {
/*
* This extends Scherer-Scott dual stack algorithm, differing,
* among other ways, by using "covering" nodes rather than
@@ -193,7 +194,7 @@
/** Node is fulfilling another unfulfilled DATA or REQUEST */
static final int FULFILLING = 2;
- /** Return true if m has fulfilling bit set */
+ /** Returns true if m has fulfilling bit set. */
static boolean isFulfilling(int m) { return (m & FULFILLING) != 0; }
/** Node class for TransferStacks. */
@@ -292,7 +293,8 @@
/**
* Puts or takes an item.
*/
- Object transfer(Object e, boolean timed, long nanos) {
+ @SuppressWarnings("unchecked")
+ E transfer(E e, boolean timed, long nanos) {
/*
* Basic algorithm is to loop trying one of three actions:
*
@@ -333,7 +335,7 @@
}
if ((h = head) != null && h.next == s)
casHead(h, s.next); // help s's fulfiller
- return (mode == REQUEST) ? m.item : s.item;
+ return (E) ((mode == REQUEST) ? m.item : s.item);
}
} else if (!isFulfilling(h.mode)) { // try to fulfill
if (h.isCancelled()) // already cancelled
@@ -349,7 +351,7 @@
SNode mn = m.next;
if (m.tryMatch(s)) {
casHead(s, mn); // pop both s and m
- return (mode == REQUEST) ? m.item : s.item;
+ return (E) ((mode == REQUEST) ? m.item : s.item);
} else // lost match
s.casNext(m, mn); // help unlink
}
@@ -400,7 +402,7 @@
* and don't wait at all, so are trapped in transfer
* method rather than calling awaitFulfill.
*/
- long lastTime = timed ? System.nanoTime() : 0;
+ final long deadline = timed ? System.nanoTime() + nanos : 0L;
Thread w = Thread.currentThread();
int spins = (shouldSpin(s) ?
(timed ? maxTimedSpins : maxUntimedSpins) : 0);
@@ -411,10 +413,8 @@
if (m != null)
return m;
if (timed) {
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
- if (nanos <= 0) {
+ nanos = deadline - System.nanoTime();
+ if (nanos <= 0L) {
s.tryCancel();
continue;
}
@@ -492,7 +492,7 @@
}
/** Dual Queue */
- static final class TransferQueue extends Transferer {
+ static final class TransferQueue<E> extends Transferer<E> {
/*
* This extends Scherer-Scott dual queue algorithm, differing,
* among other ways, by using modes within nodes rather than
@@ -570,7 +570,7 @@
/**
* Reference to a cancelled node that might not yet have been
* unlinked from queue because it was the last inserted node
- * when it cancelled.
+ * when it was cancelled.
*/
transient volatile QNode cleanMe;
@@ -609,7 +609,8 @@
/**
* Puts or takes an item.
*/
- Object transfer(Object e, boolean timed, long nanos) {
+ @SuppressWarnings("unchecked")
+ E transfer(E e, boolean timed, long nanos) {
/* Basic algorithm is to loop trying to take either of
* two actions:
*
@@ -672,7 +673,7 @@
s.item = s;
s.waiter = null;
}
- return (x != null) ? x : e;
+ return (x != null) ? (E)x : e;
} else { // complementary-mode
QNode m = h.next; // node to fulfill
@@ -689,7 +690,7 @@
advanceHead(h, m); // successfully fulfilled
LockSupport.unpark(m.waiter);
- return (x != null) ? x : e;
+ return (x != null) ? (E)x : e;
}
}
}
@@ -703,9 +704,9 @@
* @param nanos timeout value
* @return matched item, or s if cancelled
*/
- Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
+ Object awaitFulfill(QNode s, E e, boolean timed, long nanos) {
/* Same idea as TransferStack.awaitFulfill */
- long lastTime = timed ? System.nanoTime() : 0;
+ final long deadline = timed ? System.nanoTime() + nanos : 0L;
Thread w = Thread.currentThread();
int spins = ((head.next == s) ?
(timed ? maxTimedSpins : maxUntimedSpins) : 0);
@@ -716,10 +717,8 @@
if (x != e)
return x;
if (timed) {
- long now = System.nanoTime();
- nanos -= now - lastTime;
- lastTime = now;
- if (nanos <= 0) {
+ nanos = deadline - System.nanoTime();
+ if (nanos <= 0L) {
s.tryCancel(e);
continue;
}
@@ -816,23 +815,23 @@
* isn't a noticeable performance penalty for using volatile
* instead of final here.
*/
- private transient volatile Transferer transferer;
+ private transient volatile Transferer<E> transferer;
/**
- * Creates a <tt>SynchronousQueue</tt> with nonfair access policy.
+ * Creates a {@code SynchronousQueue} with nonfair access policy.
*/
public SynchronousQueue() {
this(false);
}
/**
- * Creates a <tt>SynchronousQueue</tt> with the specified fairness policy.
+ * Creates a {@code SynchronousQueue} with the specified fairness policy.
*
* @param fair if true, waiting threads contend in FIFO order for
* access; otherwise the order is unspecified.
*/
public SynchronousQueue(boolean fair) {
- transferer = fair ? new TransferQueue() : new TransferStack();
+ transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}
/**
@@ -842,9 +841,9 @@
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
- public void put(E o) throws InterruptedException {
- if (o == null) throw new NullPointerException();
- if (transferer.transfer(o, false, 0) == null) {
+ public void put(E e) throws InterruptedException {
+ if (e == null) throw new NullPointerException();
+ if (transferer.transfer(e, false, 0) == null) {
Thread.interrupted();
throw new InterruptedException();
}
@@ -854,15 +853,15 @@
* Inserts the specified element into this queue, waiting if necessary
* up to the specified wait time for another thread to receive it.
*
- * @return <tt>true</tt> if successful, or <tt>false</tt> if the
- * specified waiting time elapses before a consumer appears.
+ * @return {@code true} if successful, or {@code false} if the
+ * specified waiting time elapses before a consumer appears
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
- public boolean offer(E o, long timeout, TimeUnit unit)
+ public boolean offer(E e, long timeout, TimeUnit unit)
throws InterruptedException {
- if (o == null) throw new NullPointerException();
- if (transferer.transfer(o, true, unit.toNanos(timeout)) != null)
+ if (e == null) throw new NullPointerException();
+ if (transferer.transfer(e, true, unit.toNanos(timeout)) != null)
return true;
if (!Thread.interrupted())
return false;
@@ -874,8 +873,8 @@
* waiting to receive it.
*
* @param e the element to add
- * @return <tt>true</tt> if the element was added to this queue, else
- * <tt>false</tt>
+ * @return {@code true} if the element was added to this queue, else
+ * {@code false}
* @throws NullPointerException if the specified element is null
*/
public boolean offer(E e) {
@@ -891,9 +890,9 @@
* @throws InterruptedException {@inheritDoc}
*/
public E take() throws InterruptedException {
- Object e = transferer.transfer(null, false, 0);
+ E e = transferer.transfer(null, false, 0);
if (e != null)
- return (E)e;
+ return e;
Thread.interrupted();
throw new InterruptedException();
}
@@ -903,14 +902,14 @@
* if necessary up to the specified wait time, for another thread
* to insert it.
*
- * @return the head of this queue, or <tt>null</tt> if the
- * specified waiting time elapses before an element is present.
+ * @return the head of this queue, or {@code null} if the
+ * specified waiting time elapses before an element is present
* @throws InterruptedException {@inheritDoc}
*/
public E poll(long timeout, TimeUnit unit) throws InterruptedException {
- Object e = transferer.transfer(null, true, unit.toNanos(timeout));
+ E e = transferer.transfer(null, true, unit.toNanos(timeout));
if (e != null || !Thread.interrupted())
- return (E)e;
+ return e;
throw new InterruptedException();
}
@@ -918,18 +917,18 @@
* Retrieves and removes the head of this queue, if another thread
* is currently making an element available.
*
- * @return the head of this queue, or <tt>null</tt> if no
- * element is available.
+ * @return the head of this queue, or {@code null} if no
+ * element is available
*/
public E poll() {
- return (E)transferer.transfer(null, true, 0);
+ return transferer.transfer(null, true, 0);
}
/**
- * Always returns <tt>true</tt>.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Always returns {@code true}.
+ * A {@code SynchronousQueue} has no internal capacity.
*
- * @return <tt>true</tt>
+ * @return {@code true}
*/
public boolean isEmpty() {
return true;
@@ -937,9 +936,9 @@
/**
* Always returns zero.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * A {@code SynchronousQueue} has no internal capacity.
*
- * @return zero.
+ * @return zero
*/
public int size() {
return 0;
@@ -947,9 +946,9 @@
/**
* Always returns zero.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * A {@code SynchronousQueue} has no internal capacity.
*
- * @return zero.
+ * @return zero
*/
public int remainingCapacity() {
return 0;
@@ -957,80 +956,80 @@
/**
* Does nothing.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * A {@code SynchronousQueue} has no internal capacity.
*/
public void clear() {
}
/**
- * Always returns <tt>false</tt>.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Always returns {@code false}.
+ * A {@code SynchronousQueue} has no internal capacity.
*
* @param o the element
- * @return <tt>false</tt>
+ * @return {@code false}
*/
public boolean contains(Object o) {
return false;
}
/**
- * Always returns <tt>false</tt>.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Always returns {@code false}.
+ * A {@code SynchronousQueue} has no internal capacity.
*
* @param o the element to remove
- * @return <tt>false</tt>
+ * @return {@code false}
*/
public boolean remove(Object o) {
return false;
}
/**
- * Returns <tt>false</tt> unless the given collection is empty.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Returns {@code false} unless the given collection is empty.
+ * A {@code SynchronousQueue} has no internal capacity.
*
* @param c the collection
- * @return <tt>false</tt> unless given collection is empty
+ * @return {@code false} unless given collection is empty
*/
public boolean containsAll(Collection<?> c) {
return c.isEmpty();
}
/**
- * Always returns <tt>false</tt>.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Always returns {@code false}.
+ * A {@code SynchronousQueue} has no internal capacity.
*
* @param c the collection
- * @return <tt>false</tt>
+ * @return {@code false}
*/
public boolean removeAll(Collection<?> c) {
return false;
}
/**
- * Always returns <tt>false</tt>.
- * A <tt>SynchronousQueue</tt> has no internal capacity.
+ * Always returns {@code false}.
+ * A {@code SynchronousQueue} has no internal capacity.
*
* @param c the collection
- * @return <tt>false</tt>
+ * @return {@code false}
*/
public boolean retainAll(Collection<?> c) {
return false;
}
/**
- * Always returns <tt>null</tt>.
- * A <tt>SynchronousQueue</tt> does not return elements
+ * Always returns {@code null}.
+ * A {@code SynchronousQueue} does not return elements
* unless actively waited on.
*
- * @return <tt>null</tt>
+ * @return {@code null}
*/
public E peek() {
return null;
}
/**
- * Returns an empty iterator in which <tt>hasNext</tt> always returns
- * <tt>false</tt>.
+ * Returns an empty iterator in which {@code hasNext} always returns
+ * {@code false}.
*
* @return an empty iterator
*/
@@ -1058,7 +1057,7 @@
}
/**
- * Sets the zeroeth element of the specified array to <tt>null</tt>
+ * Sets the zeroeth element of the specified array to {@code null}
* (if the array has non-zero length) and returns it.
*
* @param a the array
@@ -1117,6 +1116,7 @@
* object is ever serialized or deserialized.
*/
+ @SuppressWarnings("serial")
static class WaitQueue implements java.io.Serializable { }
static class LifoWaitQueue extends WaitQueue {
private static final long serialVersionUID = -3633113410248163686L;
@@ -1129,9 +1129,7 @@
private WaitQueue waitingConsumers;
/**
- * Saves the state to a stream (that is, serializes it).
- *
- * @param s the stream
+ * Saves this queue to a stream (that is, serializes it).
*/
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
@@ -1149,13 +1147,16 @@
s.defaultWriteObject();
}
+ /**
+ * Reconstitutes this queue from a stream (that is, deserializes it).
+ */
private void readObject(final java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
if (waitingProducers instanceof FifoWaitQueue)
- transferer = new TransferQueue();
+ transferer = new TransferQueue<E>();
else
- transferer = new TransferStack();
+ transferer = new TransferStack<E>();
}
// Unsafe mechanics
diff --git a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
index 331e225..9586293 100644
--- a/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
+++ b/luni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
@@ -5,8 +5,10 @@
*/
package java.util.concurrent;
-import java.util.concurrent.locks.*;
-import java.util.concurrent.atomic.*;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;
// BEGIN android-note
@@ -48,22 +50,23 @@
* corePoolSize (see {@link #getCorePoolSize}) and
* maximumPoolSize (see {@link #getMaximumPoolSize}).
*
- * When a new task is submitted in method {@link #execute}, and fewer
- * than corePoolSize threads are running, a new thread is created to
- * handle the request, even if other worker threads are idle. If
- * there are more than corePoolSize but less than maximumPoolSize
- * threads running, a new thread will be created only if the queue is
- * full. By setting corePoolSize and maximumPoolSize the same, you
- * create a fixed-size thread pool. By setting maximumPoolSize to an
- * essentially unbounded value such as {@code Integer.MAX_VALUE}, you
- * allow the pool to accommodate an arbitrary number of concurrent
- * tasks. Most typically, core and maximum pool sizes are set only
- * upon construction, but they may also be changed dynamically using
- * {@link #setCorePoolSize} and {@link #setMaximumPoolSize}. </dd>
+ * When a new task is submitted in method {@link #execute(Runnable)},
+ * and fewer than corePoolSize threads are running, a new thread is
+ * created to handle the request, even if other worker threads are
+ * idle. If there are more than corePoolSize but less than
+ * maximumPoolSize threads running, a new thread will be created only
+ * if the queue is full. By setting corePoolSize and maximumPoolSize
+ * the same, you create a fixed-size thread pool. By setting
+ * maximumPoolSize to an essentially unbounded value such as {@code
+ * Integer.MAX_VALUE}, you allow the pool to accommodate an arbitrary
+ * number of concurrent tasks. Most typically, core and maximum pool
+ * sizes are set only upon construction, but they may also be changed
+ * dynamically using {@link #setCorePoolSize} and {@link
+ * #setMaximumPoolSize}. </dd>
*
* <dt>On-demand construction</dt>
*
- * <dd> By default, even core threads are initially created and
+ * <dd>By default, even core threads are initially created and
* started only when new tasks arrive, but this can be overridden
* dynamically using method {@link #prestartCoreThread} or {@link
* #prestartAllCoreThreads}. You probably want to prestart threads if
@@ -85,17 +88,17 @@
*
* <dd>If the pool currently has more than corePoolSize threads,
* excess threads will be terminated if they have been idle for more
- * than the keepAliveTime (see {@link #getKeepAliveTime}). This
- * provides a means of reducing resource consumption when the pool is
- * not being actively used. If the pool becomes more active later, new
- * threads will be constructed. This parameter can also be changed
- * dynamically using method {@link #setKeepAliveTime}. Using a value
- * of {@code Long.MAX_VALUE} {@link TimeUnit#NANOSECONDS} effectively
- * disables idle threads from ever terminating prior to shut down. By
- * default, the keep-alive policy applies only when there are more
- * than corePoolSizeThreads. But method {@link
- * #allowCoreThreadTimeOut(boolean)} can be used to apply this
- * time-out policy to core threads as well, so long as the
+ * than the keepAliveTime (see {@link #getKeepAliveTime(TimeUnit)}).
+ * This provides a means of reducing resource consumption when the
+ * pool is not being actively used. If the pool becomes more active
+ * later, new threads will be constructed. This parameter can also be
+ * changed dynamically using method {@link #setKeepAliveTime(long,
+ * TimeUnit)}. Using a value of {@code Long.MAX_VALUE} {@link
+ * TimeUnit#NANOSECONDS} effectively disables idle threads from ever
+ * terminating prior to shut down. By default, the keep-alive policy
+ * applies only when there are more than corePoolSize threads. But
+ * method {@link #allowCoreThreadTimeOut(boolean)} can be used to
+ * apply this time-out policy to core threads as well, so long as the
* keepAliveTime value is non-zero. </dd>
*
* <dt>Queuing</dt>
@@ -165,14 +168,14 @@
*
* <dt>Rejected tasks</dt>
*
- * <dd> New tasks submitted in method {@link #execute} will be
- * <em>rejected</em> when the Executor has been shut down, and also
- * when the Executor uses finite bounds for both maximum threads and
- * work queue capacity, and is saturated. In either case, the {@code
- * execute} method invokes the {@link
- * RejectedExecutionHandler#rejectedExecution} method of its {@link
- * RejectedExecutionHandler}. Four predefined handler policies are
- * provided:
+ * <dd>New tasks submitted in method {@link #execute(Runnable)} will be
+ * <em>rejected</em> when the Executor has been shut down, and also when
+ * the Executor uses finite bounds for both maximum threads and work queue
+ * capacity, and is saturated. In either case, the {@code execute} method
+ * invokes the {@link
+ * RejectedExecutionHandler#rejectedExecution(Runnable, ThreadPoolExecutor)}
+ * method of its {@link RejectedExecutionHandler}. Four predefined handler
+ * policies are provided:
*
* <ol>
*
@@ -202,30 +205,31 @@
*
* <dt>Hook methods</dt>
*
- * <dd>This class provides {@code protected} overridable {@link
- * #beforeExecute} and {@link #afterExecute} methods that are called
+ * <dd>This class provides {@code protected} overridable
+ * {@link #beforeExecute(Thread, Runnable)} and
+ * {@link #afterExecute(Runnable, Throwable)} methods that are called
* before and after execution of each task. These can be used to
* manipulate the execution environment; for example, reinitializing
- * ThreadLocals, gathering statistics, or adding log
- * entries. Additionally, method {@link #terminated} can be overridden
- * to perform any special processing that needs to be done once the
- * Executor has fully terminated.
+ * ThreadLocals, gathering statistics, or adding log entries.
+ * Additionally, method {@link #terminated} can be overridden to perform
+ * any special processing that needs to be done once the Executor has
+ * fully terminated.
*
* <p>If hook or callback methods throw exceptions, internal worker
* threads may in turn fail and abruptly terminate.</dd>
*
* <dt>Queue maintenance</dt>
*
- * <dd> Method {@link #getQueue} allows access to the work queue for
- * purposes of monitoring and debugging. Use of this method for any
- * other purpose is strongly discouraged. Two supplied methods,
- * {@link #remove} and {@link #purge} are available to assist in
- * storage reclamation when large numbers of queued tasks become
- * cancelled.</dd>
+ * <dd>Method {@link #getQueue()} allows access to the work queue
+ * for purposes of monitoring and debugging. Use of this method for
+ * any other purpose is strongly discouraged. Two supplied methods,
+ * {@link #remove(Runnable)} and {@link #purge} are available to
+ * assist in storage reclamation when large numbers of queued tasks
+ * become cancelled.</dd>
*
* <dt>Finalization</dt>
*
- * <dd> A pool that is no longer referenced in a program <em>AND</em>
+ * <dd>A pool that is no longer referenced in a program <em>AND</em>
* has no remaining threads will be {@code shutdown} automatically. If
* you would like to ensure that unreferenced pools are reclaimed even
* if users forget to call {@link #shutdown}, then you must arrange
@@ -235,7 +239,7 @@
*
* </dl>
*
- * <p> <b>Extension example</b>. Most extensions of this class
+ * <p><b>Extension example</b>. Most extensions of this class
* override one or more of the protected hook methods. For example,
* here is a subclass that adds a simple pause/resume feature:
*
@@ -304,7 +308,7 @@
* bookkeeping before terminating. The user-visible pool size is
* reported as the current size of the workers set.
*
- * The runState provides the main lifecyle control, taking on values:
+ * The runState provides the main lifecycle control, taking on values:
*
* RUNNING: Accept new tasks and process queued tasks
* SHUTDOWN: Don't accept new tasks, but process queued tasks
@@ -374,14 +378,14 @@
}
/**
- * Attempt to CAS-increment the workerCount field of ctl.
+ * Attempts to CAS-increment the workerCount field of ctl.
*/
private boolean compareAndIncrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect + 1);
}
/**
- * Attempt to CAS-decrement the workerCount field of ctl.
+ * Attempts to CAS-decrement the workerCount field of ctl.
*/
private boolean compareAndDecrementWorkerCount(int expect) {
return ctl.compareAndSet(expect, expect - 1);
@@ -461,10 +465,15 @@
* policy limiting the number of threads. Even though it is not
* treated as an error, failure to create threads may result in
* new tasks being rejected or existing ones remaining stuck in
- * the queue. On the other hand, no special precautions exist to
- * handle OutOfMemoryErrors that might be thrown while trying to
- * create threads, since there is generally no recourse from
- * within this class.
+ * the queue.
+ *
+ * We go further and preserve pool invariants even in the face of
+ * errors such as OutOfMemoryError, that might be thrown while
+ * trying to create threads. Such errors are rather common due to
+ * the need to allocate a native stack in Thread.start, and users
+ * will want to perform clean pool shutdown to clean up. There
+ * will likely be enough memory available for the cleanup code to
+ * complete without encountering yet another OutOfMemoryError.
*/
private volatile ThreadFactory threadFactory;
@@ -538,9 +547,13 @@
* task execution. This protects against interrupts that are
* intended to wake up a worker thread waiting for a task from
* instead interrupting a task being run. We implement a simple
- * non-reentrant mutual exclusion lock rather than use ReentrantLock
- * because we do not want worker tasks to be able to reacquire the
- * lock when they invoke pool control methods like setCorePoolSize.
+ * non-reentrant mutual exclusion lock rather than use
+ * ReentrantLock because we do not want worker tasks to be able to
+ * reacquire the lock when they invoke pool control methods like
+ * setCorePoolSize. Additionally, to suppress interrupts until
+ * the thread actually starts running tasks, we initialize lock
+ * state to a negative value, and clear it upon start (in
+ * runWorker).
*/
private final class Worker
extends AbstractQueuedSynchronizer
@@ -564,6 +577,7 @@
* @param firstTask the first task (null if none)
*/
Worker(Runnable firstTask) {
+ setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
@@ -579,7 +593,7 @@
// The value 1 represents the locked state.
protected boolean isHeldExclusively() {
- return getState() == 1;
+ return getState() != 0;
}
protected boolean tryAcquire(int unused) {
@@ -600,6 +614,16 @@
public boolean tryLock() { return tryAcquire(1); }
public void unlock() { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
+
+ void interruptIfStarted() {
+ Thread t;
+ if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
+ try {
+ t.interrupt();
+ } catch (SecurityException ignore) {
+ }
+ }
+ }
}
/*
@@ -698,12 +722,8 @@
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
- for (Worker w : workers) {
- try {
- w.thread.interrupt();
- } catch (SecurityException ignore) {
- }
- }
+ for (Worker w : workers)
+ w.interruptIfStarted();
} finally {
mainLock.unlock();
}
@@ -760,19 +780,6 @@
private static final boolean ONLY_ONE = true;
- /**
- * Ensures that unless the pool is stopping, the current thread
- * does not have its interrupt set. This requires a double-check
- * of state in case the interrupt was cleared concurrently with a
- * shutdownNow -- if so, the interrupt is re-enabled.
- */
- private void clearInterruptsForTaskRun() {
- if (runStateLessThan(ctl.get(), STOP) &&
- Thread.interrupted() &&
- runStateAtLeast(ctl.get(), STOP))
- Thread.currentThread().interrupt();
- }
-
/*
* Misc utilities, most of which are also exported to
* ScheduledThreadPoolExecutor
@@ -813,7 +820,7 @@
*/
private List<Runnable> drainQueue() {
BlockingQueue<Runnable> q = workQueue;
- List<Runnable> taskList = new ArrayList<Runnable>();
+ ArrayList<Runnable> taskList = new ArrayList<Runnable>();
q.drainTo(taskList);
if (!q.isEmpty()) {
for (Runnable r : q.toArray(new Runnable[0])) {
@@ -832,12 +839,13 @@
* Checks if a new worker can be added with respect to current
* pool state and the given bound (either core or maximum). If so,
* the worker count is adjusted accordingly, and, if possible, a
- * new worker is created and started running firstTask as its
+ * new worker is created and started, running firstTask as its
* first task. This method returns false if the pool is stopped or
* eligible to shut down. It also returns false if the thread
- * factory fails to create a thread when asked, which requires a
- * backout of workerCount, and a recheck for termination, in case
- * the existence of this worker was holding up termination.
+ * factory fails to create a thread when asked. If the thread
+ * creation fails, either due to the thread factory returning
+ * null, or due to an exception (typically OutOfMemoryError in
+ * Thread.start()), we roll back cleanly.
*
* @param firstTask the task the new thread should run first (or
* null if none). Workers are created with an initial first task
@@ -880,46 +888,64 @@
}
}
- Worker w = new Worker(firstTask);
- Thread t = w.thread;
+ boolean workerStarted = false;
+ boolean workerAdded = false;
+ Worker w = null;
+ try {
+ w = new Worker(firstTask);
+ final Thread t = w.thread;
+ if (t != null) {
+ final ReentrantLock mainLock = this.mainLock;
+ mainLock.lock();
+ try {
+ // Recheck while holding lock.
+ // Back out on ThreadFactory failure or if
+ // shut down before lock acquired.
+ int rs = runStateOf(ctl.get());
+ if (rs < SHUTDOWN ||
+ (rs == SHUTDOWN && firstTask == null)) {
+ if (t.isAlive()) // precheck that t is startable
+ throw new IllegalThreadStateException();
+ workers.add(w);
+ int s = workers.size();
+ if (s > largestPoolSize)
+ largestPoolSize = s;
+ workerAdded = true;
+ }
+ } finally {
+ mainLock.unlock();
+ }
+ if (workerAdded) {
+ t.start();
+ workerStarted = true;
+ }
+ }
+ } finally {
+ if (! workerStarted)
+ addWorkerFailed(w);
+ }
+ return workerStarted;
+ }
+
+ /**
+ * Rolls back the worker thread creation.
+ * - removes worker from workers, if present
+ * - decrements worker count
+ * - rechecks for termination, in case the existence of this
+ * worker was holding up termination
+ */
+ private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
- // Recheck while holding lock.
- // Back out on ThreadFactory failure or if
- // shut down before lock acquired.
- int c = ctl.get();
- int rs = runStateOf(c);
-
- if (t == null ||
- (rs >= SHUTDOWN &&
- ! (rs == SHUTDOWN &&
- firstTask == null))) {
- decrementWorkerCount();
- tryTerminate();
- return false;
- }
-
- workers.add(w);
-
- int s = workers.size();
- if (s > largestPoolSize)
- largestPoolSize = s;
+ if (w != null)
+ workers.remove(w);
+ decrementWorkerCount();
+ tryTerminate();
} finally {
mainLock.unlock();
}
-
- t.start();
- // It is possible (but unlikely) for a thread to have been
- // added to workers, but not yet started, during transition to
- // STOP, which could result in a rare missed interrupt,
- // because Thread.interrupt is not guaranteed to have any effect
- // on a non-yet-started Thread (see Thread#interrupt).
- if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted())
- t.interrupt();
-
- return true;
}
/**
@@ -974,7 +1000,8 @@
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
- * both before and after the timed wait.
+ * both before and after the timed wait, and if the queue is
+ * non-empty, this worker is not the last thread in the pool.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
@@ -982,7 +1009,6 @@
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
- retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
@@ -993,20 +1019,16 @@
return null;
}
- boolean timed; // Are workers subject to culling?
+ int wc = workerCountOf(c);
- for (;;) {
- int wc = workerCountOf(c);
- timed = allowCoreThreadTimeOut || wc > corePoolSize;
+ // Are workers subject to culling?
+ boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
- if (wc <= maximumPoolSize && ! (timedOut && timed))
- break;
+ if ((wc > maximumPoolSize || (timed && timedOut))
+ && (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
- c = ctl.get(); // Re-read ctl
- if (runStateOf(c) != rs)
- continue retry;
- // else CAS failed due to workerCount change; retry inner loop
+ continue;
}
try {
@@ -1035,9 +1057,9 @@
* usually leads processWorkerExit to replace this thread.
*
* 2. Before running any task, the lock is acquired to prevent
- * other pool interrupts while the task is executing, and
- * clearInterruptsForTaskRun called to ensure that unless pool is
- * stopping, this thread does not have its interrupt set.
+ * other pool interrupts while the task is executing, and then we
+ * ensure that unless pool is stopping, this thread does not have
+ * its interrupt set.
*
* 3. Each task run is preceded by a call to beforeExecute, which
* might throw an exception, in which case we cause thread to die
@@ -1045,12 +1067,12 @@
* the task.
*
* 4. Assuming beforeExecute completes normally, we run the task,
- * gathering any of its thrown exceptions to send to
- * afterExecute. We separately handle RuntimeException, Error
- * (both of which the specs guarantee that we trap) and arbitrary
- * Throwables. Because we cannot rethrow Throwables within
- * Runnable.run, we wrap them within Errors on the way out (to the
- * thread's UncaughtExceptionHandler). Any thrown exception also
+ * gathering any of its thrown exceptions to send to afterExecute.
+ * We separately handle RuntimeException, Error (both of which the
+ * specs guarantee that we trap) and arbitrary Throwables.
+ * Because we cannot rethrow Throwables within Runnable.run, we
+ * wrap them within Errors on the way out (to the thread's
+ * UncaughtExceptionHandler). Any thrown exception also
* conservatively causes thread to die.
*
* 5. After task.run completes, we call afterExecute, which may
@@ -1066,15 +1088,25 @@
* @param w the worker
*/
final void runWorker(Worker w) {
+ Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
+ w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
- clearInterruptsForTaskRun();
+ // If pool is stopping, ensure thread is interrupted;
+ // if not, ensure thread is not interrupted. This
+ // requires a recheck in second case to deal with
+ // shutdownNow race while clearing interrupt
+ if ((runStateAtLeast(ctl.get(), STOP) ||
+ (Thread.interrupted() &&
+ runStateAtLeast(ctl.get(), STOP))) &&
+ !wt.isInterrupted())
+ wt.interrupt();
try {
- beforeExecute(w.thread, task);
+ beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
@@ -1374,7 +1406,7 @@
* ignored or suppressed interruption, causing this executor not
* to properly terminate.
*
- * @return true if terminating but not yet terminated
+ * @return {@code true} if terminating but not yet terminated
*/
public boolean isTerminating() {
int c = ctl.get();
@@ -1428,7 +1460,7 @@
* Returns the thread factory used to create new threads.
*
* @return the current thread factory
- * @see #setThreadFactory
+ * @see #setThreadFactory(ThreadFactory)
*/
public ThreadFactory getThreadFactory() {
return threadFactory;
@@ -1451,7 +1483,7 @@
* Returns the current handler for unexecutable tasks.
*
* @return the current handler
- * @see #setRejectedExecutionHandler
+ * @see #setRejectedExecutionHandler(RejectedExecutionHandler)
*/
public RejectedExecutionHandler getRejectedExecutionHandler() {
return handler;
@@ -1623,7 +1655,7 @@
* @param unit the time unit of the {@code time} argument
* @throws IllegalArgumentException if {@code time} less than zero or
* if {@code time} is zero and {@code allowsCoreThreadTimeOut}
- * @see #getKeepAliveTime
+ * @see #getKeepAliveTime(TimeUnit)
*/
public void setKeepAliveTime(long time, TimeUnit unit) {
if (time < 0)
@@ -1644,7 +1676,7 @@
*
* @param unit the desired time unit of the result
* @return the time limit
- * @see #setKeepAliveTime
+ * @see #setKeepAliveTime(long, TimeUnit)
*/
public long getKeepAliveTime(TimeUnit unit) {
return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
@@ -1669,7 +1701,7 @@
* present, thus causing it not to be run if it has not already
* started.
*
- * <p> This method may be useful as one part of a cancellation
+ * <p>This method may be useful as one part of a cancellation
* scheme. It may fail to remove tasks that have been converted
* into other forms before being placed on the internal queue. For
* example, a task entered using {@code submit} might be
@@ -1678,7 +1710,7 @@
* remove those Futures that have been cancelled.
*
* @param task the task to remove
- * @return true if the task was removed
+ * @return {@code true} if the task was removed
*/
public boolean remove(Runnable task) {
boolean removed = workQueue.remove(task);
@@ -1973,7 +2005,7 @@
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
- * @throws RejectedExecutionException always.
+ * @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
diff --git a/luni/src/main/java/java/util/concurrent/TimeUnit.java b/luni/src/main/java/java/util/concurrent/TimeUnit.java
index 50f6ce0..eb2c495 100644
--- a/luni/src/main/java/java/util/concurrent/TimeUnit.java
+++ b/luni/src/main/java/java/util/concurrent/TimeUnit.java
@@ -7,10 +7,10 @@
package java.util.concurrent;
/**
- * A <tt>TimeUnit</tt> represents time durations at a given unit of
+ * A {@code TimeUnit} represents time durations at a given unit of
* granularity and provides utility methods to convert across units,
* and to perform timing and delay operations in these units. A
- * <tt>TimeUnit</tt> does not maintain time information, but only
+ * {@code TimeUnit} does not maintain time information, but only
* helps organize and use time representations that may be maintained
* separately across various contexts. A nanosecond is defined as one
* thousandth of a microsecond, a microsecond as one thousandth of a
@@ -18,7 +18,7 @@
* as sixty seconds, an hour as sixty minutes, and a day as twenty four
* hours.
*
- * <p>A <tt>TimeUnit</tt> is mainly used to inform time-based methods
+ * <p>A {@code TimeUnit} is mainly used to inform time-based methods
* how a given timing parameter should be interpreted. For example,
* the following code will timeout in 50 milliseconds if the {@link
* java.util.concurrent.locks.Lock lock} is not available:
@@ -34,7 +34,7 @@
*
* Note however, that there is no guarantee that a particular timeout
* implementation will be able to notice the passage of time at the
- * same granularity as the given <tt>TimeUnit</tt>.
+ * same granularity as the given {@code TimeUnit}.
*
* @since 1.5
* @author Doug Lea
@@ -148,31 +148,31 @@
* Convert the given time duration in the given unit to this
* unit. Conversions from finer to coarser granularities
* truncate, so lose precision. For example converting
- * <tt>999</tt> milliseconds to seconds results in
- * <tt>0</tt>. Conversions from coarser to finer granularities
+ * {@code 999} milliseconds to seconds results in
+ * {@code 0}. Conversions from coarser to finer granularities
* with arguments that would numerically overflow saturate to
- * <tt>Long.MIN_VALUE</tt> if negative or <tt>Long.MAX_VALUE</tt>
+ * {@code Long.MIN_VALUE} if negative or {@code Long.MAX_VALUE}
* if positive.
*
* <p>For example, to convert 10 minutes to milliseconds, use:
- * <tt>TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)</tt>
+ * {@code TimeUnit.MILLISECONDS.convert(10L, TimeUnit.MINUTES)}
*
- * @param sourceDuration the time duration in the given <tt>sourceUnit</tt>
- * @param sourceUnit the unit of the <tt>sourceDuration</tt> argument
+ * @param sourceDuration the time duration in the given {@code sourceUnit}
+ * @param sourceUnit the unit of the {@code sourceDuration} argument
* @return the converted duration in this unit,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
*/
public long convert(long sourceDuration, TimeUnit sourceUnit) {
throw new AbstractMethodError();
}
/**
- * Equivalent to <tt>NANOSECONDS.convert(duration, this)</tt>.
+ * Equivalent to {@code NANOSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
*/
public long toNanos(long duration) {
@@ -180,11 +180,11 @@
}
/**
- * Equivalent to <tt>MICROSECONDS.convert(duration, this)</tt>.
+ * Equivalent to {@code MICROSECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
*/
public long toMicros(long duration) {
@@ -192,11 +192,11 @@
}
/**
- * Equivalent to <tt>MILLISECONDS.convert(duration, this)</tt>.
+ * Equivalent to {@code MILLISECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
*/
public long toMillis(long duration) {
@@ -204,11 +204,11 @@
}
/**
- * Equivalent to <tt>SECONDS.convert(duration, this)</tt>.
+ * Equivalent to {@code SECONDS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
*/
public long toSeconds(long duration) {
@@ -216,11 +216,11 @@
}
/**
- * Equivalent to <tt>MINUTES.convert(duration, this)</tt>.
+ * Equivalent to {@code MINUTES.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
* @since 1.6
*/
@@ -229,11 +229,11 @@
}
/**
- * Equivalent to <tt>HOURS.convert(duration, this)</tt>.
+ * Equivalent to {@code HOURS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration,
- * or <tt>Long.MIN_VALUE</tt> if conversion would negatively
- * overflow, or <tt>Long.MAX_VALUE</tt> if it would positively overflow.
+ * or {@code Long.MIN_VALUE} if conversion would negatively
+ * overflow, or {@code Long.MAX_VALUE} if it would positively overflow.
* @see #convert
* @since 1.6
*/
@@ -242,7 +242,7 @@
}
/**
- * Equivalent to <tt>DAYS.convert(duration, this)</tt>.
+ * Equivalent to {@code DAYS.convert(duration, this)}.
* @param duration the duration
* @return the converted duration
* @see #convert
@@ -265,9 +265,9 @@
* Performs a timed {@link Object#wait(long, int) Object.wait}
* using this time unit.
* This is a convenience method that converts timeout arguments
- * into the form required by the <tt>Object.wait</tt> method.
+ * into the form required by the {@code Object.wait} method.
*
- * <p>For example, you could implement a blocking <tt>poll</tt>
+ * <p>For example, you could implement a blocking {@code poll}
* method (see {@link BlockingQueue#poll BlockingQueue.poll})
* using:
*
@@ -298,7 +298,7 @@
* Performs a timed {@link Thread#join(long, int) Thread.join}
* using this time unit.
* This is a convenience method that converts time arguments into the
- * form required by the <tt>Thread.join</tt> method.
+ * form required by the {@code Thread.join} method.
*
* @param thread the thread to wait for
* @param timeout the maximum time to wait. If less than
@@ -318,7 +318,7 @@
* Performs a {@link Thread#sleep(long, int) Thread.sleep} using
* this time unit.
* This is a convenience method that converts time arguments into the
- * form required by the <tt>Thread.sleep</tt> method.
+ * form required by the {@code Thread.sleep} method.
*
* @param timeout the minimum time to sleep. If less than
* or equal to zero, do not sleep at all.
diff --git a/luni/src/main/java/java/util/concurrent/TimeoutException.java b/luni/src/main/java/java/util/concurrent/TimeoutException.java
index 83934f0..1d7e634 100644
--- a/luni/src/main/java/java/util/concurrent/TimeoutException.java
+++ b/luni/src/main/java/java/util/concurrent/TimeoutException.java
@@ -11,7 +11,7 @@
* operations for which a timeout is specified need a means to
* indicate that the timeout has occurred. For many such operations it
* is possible to return a value that indicates timeout; when that is
- * not possible or desirable then <tt>TimeoutException</tt> should be
+ * not possible or desirable then {@code TimeoutException} should be
* declared and thrown.
*
* @since 1.5
@@ -21,13 +21,13 @@
private static final long serialVersionUID = 1900926677490660714L;
/**
- * Constructs a <tt>TimeoutException</tt> with no specified detail
+ * Constructs a {@code TimeoutException} with no specified detail
* message.
*/
public TimeoutException() {}
/**
- * Constructs a <tt>TimeoutException</tt> with the specified detail
+ * Constructs a {@code TimeoutException} with the specified detail
* message.
*
* @param message the detail message
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
index d531f25..13b12aa 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicBoolean.java
@@ -76,13 +76,13 @@
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public boolean weakCompareAndSet(boolean expect, boolean update) {
int e = expect ? 1 : 0;
@@ -126,7 +126,7 @@
/**
* Returns the String representation of the current value.
- * @return the String representation of the current value.
+ * @return the String representation of the current value
*/
public String toString() {
return Boolean.toString(get());
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
index e0a0018..d67b20a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicInteger.java
@@ -110,13 +110,13 @@
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
@@ -210,13 +210,12 @@
/**
* Returns the String representation of the current value.
- * @return the String representation of the current value.
+ * @return the String representation of the current value
*/
public String toString() {
return Integer.toString(get());
}
-
/**
* Returns the value of this {@code AtomicInteger} as an {@code int}.
*/
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
index 804a51e..1f6980d 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerArray.java
@@ -146,14 +146,14 @@
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param i the index
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(int i, int expect, int update) {
return compareAndSet(i, expect, update);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
index c7ed158..6067152 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java
@@ -8,7 +8,8 @@
import dalvik.system.VMStack; // android-added
import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
/**
* A reflection-based utility that enables atomic updates to
@@ -28,7 +29,7 @@
* @author Doug Lea
* @param <T> The type of the object holding the updatable field
*/
-public abstract class AtomicIntegerFieldUpdater<T> {
+public abstract class AtomicIntegerFieldUpdater<T> {
/**
* Creates and returns an updater for objects with the given field.
* The Class argument is needed to check that reflective types and
@@ -40,7 +41,9 @@
* @throws IllegalArgumentException if the field is not a
* volatile integer type
* @throws RuntimeException with a nested reflection-based
- * exception if the class does not hold field or is the wrong type
+ * exception if the class does not hold field or is the wrong type,
+ * or the field is inaccessible to the caller according to Java language
+ * access control
*/
public static <U> AtomicIntegerFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
return new AtomicIntegerFieldUpdaterImpl<U>(tclass, fieldName);
@@ -75,9 +78,9 @@
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
@@ -108,7 +111,6 @@
*/
public abstract void lazySet(T obj, int newValue);
-
/**
* Gets the current value held in the field of the given object managed
* by this updater.
@@ -242,19 +244,28 @@
private final Class<?> cclass;
AtomicIntegerFieldUpdaterImpl(Class<T> tclass, String fieldName) {
- Field field = null;
- Class<?> caller = null;
- int modifiers = 0;
+ final Field field;
+ final Class<?> caller;
+ final int modifiers;
try {
- field = tclass.getDeclaredField(fieldName);
+ field = tclass.getDeclaredField(fieldName); // android-changed
caller = VMStack.getStackClass2(); // android-changed
- modifiers = field.getModifiers();
+ modifiers = field.getModifiers();
// BEGIN android-removed
// sun.reflect.misc.ReflectUtil.ensureMemberAccess(
// caller, tclass, null, modifiers);
- // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // ClassLoader cl = tclass.getClassLoader();
+ // ClassLoader ccl = caller.getClassLoader();
+ // if ((ccl != null) && (ccl != cl) &&
+ // ((cl == null) || !isAncestor(cl, ccl))) {
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // }
// END android-removed
+ // BEGIN android-removed
+ // } catch (PrivilegedActionException pae) {
+ // throw new RuntimeException(pae.getException());
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -272,6 +283,23 @@
offset = unsafe.objectFieldOffset(field);
}
+ // BEGIN android-removed
+ // /**
+ // * Returns true if the second classloader can be found in the first
+ // * classloader's delegation chain.
+ // * Equivalent to the inaccessible: first.isAncestor(second).
+ // */
+ // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+ // ClassLoader acl = first;
+ // do {
+ // acl = acl.getParent();
+ // if (second == acl) {
+ // return true;
+ // }
+ // } while (acl != null);
+ // return false;
+ // }
+ // END android-removed
private void fullCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
index 5e799f7..278c5b5 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLong.java
@@ -124,13 +124,13 @@
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(long expect, long update) {
return unsafe.compareAndSwapLong(this, valueOffset, expect, update);
@@ -224,13 +224,12 @@
/**
* Returns the String representation of the current value.
- * @return the String representation of the current value.
+ * @return the String representation of the current value
*/
public String toString() {
return Long.toString(get());
}
-
/**
* Returns the value of this {@code AtomicLong} as an {@code int}
* after a narrowing primitive conversion.
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
index 22edb3f..2e8c2b7 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongArray.java
@@ -106,7 +106,6 @@
unsafe.putOrderedLong(array, checkedByteOffset(i), newValue);
}
-
/**
* Atomically sets the element at position {@code i} to the given value
* and returns the old value.
@@ -146,14 +145,14 @@
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param i the index
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(int i, long expect, long update) {
return compareAndSet(i, expect, update);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
index 748ae69..0096a6b 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicLongFieldUpdater.java
@@ -8,7 +8,8 @@
import dalvik.system.VMStack; // android-added
import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
/**
* A reflection-based utility that enables atomic updates to
@@ -28,19 +29,21 @@
* @author Doug Lea
* @param <T> The type of the object holding the updatable field
*/
-public abstract class AtomicLongFieldUpdater<T> {
+public abstract class AtomicLongFieldUpdater<T> {
/**
* Creates and returns an updater for objects with the given field.
* The Class argument is needed to check that reflective types and
* generic types match.
*
* @param tclass the class of the objects holding the field
- * @param fieldName the name of the field to be updated.
+ * @param fieldName the name of the field to be updated
* @return the updater
* @throws IllegalArgumentException if the field is not a
- * volatile long type.
+ * volatile long type
* @throws RuntimeException with a nested reflection-based
- * exception if the class does not hold field or is the wrong type.
+ * exception if the class does not hold field or is the wrong type,
+ * or the field is inaccessible to the caller according to Java language
+ * access control
*/
public static <U> AtomicLongFieldUpdater<U> newUpdater(Class<U> tclass, String fieldName) {
if (AtomicLong.VM_SUPPORTS_LONG_CAS)
@@ -65,9 +68,9 @@
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
* @throws ClassCastException if {@code obj} is not an instance
- * of the class possessing the field established in the constructor.
+ * of the class possessing the field established in the constructor
*/
public abstract boolean compareAndSet(T obj, long expect, long update);
@@ -78,16 +81,16 @@
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
* @throws ClassCastException if {@code obj} is not an instance
- * of the class possessing the field established in the constructor.
+ * of the class possessing the field established in the constructor
*/
public abstract boolean weakCompareAndSet(T obj, long expect, long update);
@@ -241,18 +244,27 @@
private final Class<?> cclass;
CASUpdater(Class<T> tclass, String fieldName) {
- Field field = null;
- Class<?> caller = null;
- int modifiers = 0;
+ final Field field;
+ final Class<?> caller;
+ final int modifiers;
try {
- field = tclass.getDeclaredField(fieldName);
+ field = tclass.getDeclaredField(fieldName); // android-changed
caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
// BEGIN android-removed
// sun.reflect.misc.ReflectUtil.ensureMemberAccess(
// caller, tclass, null, modifiers);
- // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // ClassLoader cl = tclass.getClassLoader();
+ // ClassLoader ccl = caller.getClassLoader();
+ // if ((ccl != null) && (ccl != cl) &&
+ // ((cl == null) || !isAncestor(cl, ccl))) {
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // }
// END android-removed
+ // BEGIN android-removed
+ // } catch (PrivilegedActionException pae) {
+ // throw new RuntimeException(pae.getException());
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -330,14 +342,23 @@
Class<?> caller = null;
int modifiers = 0;
try {
- field = tclass.getDeclaredField(fieldName);
+ field = tclass.getDeclaredField(fieldName); // android-changed
caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
// BEGIN android-removed
// sun.reflect.misc.ReflectUtil.ensureMemberAccess(
// caller, tclass, null, modifiers);
- // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // ClassLoader cl = tclass.getClassLoader();
+ // ClassLoader ccl = caller.getClassLoader();
+ // if ((ccl != null) && (ccl != cl) &&
+ // ((cl == null) || !isAncestor(cl, ccl))) {
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // }
// END android-removed
+ // BEGIN android-removed
+ // } catch (PrivilegedActionException pae) {
+ // throw new RuntimeException(pae.getException());
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -410,4 +431,22 @@
);
}
}
+
+ // BEGIN android-removed
+ // /**
+ // * Returns true if the second classloader can be found in the first
+ // * classloader's delegation chain.
+ // * Equivalent to the inaccessible: first.isAncestor(second).
+ // */
+ // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+ // ClassLoader acl = first;
+ // do {
+ // acl = acl.getParent();
+ // if (second == acl) {
+ // return true;
+ // }
+ // } while (acl != null);
+ // return false;
+ // }
+ // END android-removed
}
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
index eaf700c..1257be0 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicMarkableReference.java
@@ -83,9 +83,9 @@
* current reference is {@code ==} to the expected reference
* and the current mark is equal to the expected mark.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
index b21e9b6..98b402a 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReference.java
@@ -15,7 +15,7 @@
* @author Doug Lea
* @param <V> The type of object referred to by this reference
*/
-public class AtomicReference<V> implements java.io.Serializable {
+public class AtomicReference<V> implements java.io.Serializable {
private static final long serialVersionUID = -1848883965231344442L;
private static final Unsafe unsafe = Unsafe.getUnsafe();
@@ -89,13 +89,13 @@
* Atomically sets the value to the given updated value
* if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(V expect, V update) {
return unsafe.compareAndSwapObject(this, valueOffset, expect, update);
@@ -117,7 +117,7 @@
/**
* Returns the String representation of the current value.
- * @return the String representation of the current value.
+ * @return the String representation of the current value
*/
public String toString() {
return String.valueOf(get());
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
index c47728d..052b839 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceArray.java
@@ -29,19 +29,18 @@
private final Object[] array; // must have exact type Object[]
static {
- int scale;
try {
unsafe = Unsafe.getUnsafe();
arrayFieldOffset = unsafe.objectFieldOffset
(AtomicReferenceArray.class.getDeclaredField("array"));
base = unsafe.arrayBaseOffset(Object[].class);
- scale = unsafe.arrayIndexScale(Object[].class);
+ int scale = unsafe.arrayIndexScale(Object[].class);
+ if ((scale & (scale - 1)) != 0)
+ throw new Error("data type scale not a power of two");
+ shift = 31 - Integer.numberOfLeadingZeros(scale);
} catch (Exception e) {
throw new Error(e);
}
- if ((scale & (scale - 1)) != 0)
- throw new Error("data type scale not a power of two");
- shift = 31 - Integer.numberOfLeadingZeros(scale);
}
private long checkedByteOffset(int i) {
@@ -96,6 +95,7 @@
return getRaw(checkedByteOffset(i));
}
+ @SuppressWarnings("unchecked")
private E getRaw(long offset) {
return (E) unsafe.getObjectVolatile(array, offset);
}
@@ -121,7 +121,6 @@
unsafe.putOrderedObject(array, checkedByteOffset(i), newValue);
}
-
/**
* Atomically sets the element at position {@code i} to the given
* value and returns the old value.
@@ -161,14 +160,14 @@
* Atomically sets the element at position {@code i} to the given
* updated value if the current value {@code ==} the expected value.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param i the index
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public final boolean weakCompareAndSet(int i, E expect, E update) {
return compareAndSet(i, expect, update);
@@ -195,7 +194,6 @@
/**
* Reconstitutes the instance from a stream (that is, deserializes it).
- * @param s the stream
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException,
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
index d23d766..eb2d73e 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java
@@ -7,7 +7,8 @@
package java.util.concurrent.atomic;
import dalvik.system.VMStack; // android-added
import sun.misc.Unsafe;
-import java.lang.reflect.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
/**
* A reflection-based utility that enables atomic updates to
@@ -45,20 +46,22 @@
* @param <T> The type of the object holding the updatable field
* @param <V> The type of the field
*/
-public abstract class AtomicReferenceFieldUpdater<T, V> {
+public abstract class AtomicReferenceFieldUpdater<T,V> {
/**
* Creates and returns an updater for objects with the given field.
* The Class arguments are needed to check that reflective types and
* generic types match.
*
- * @param tclass the class of the objects holding the field.
+ * @param tclass the class of the objects holding the field
* @param vclass the class of the field
- * @param fieldName the name of the field to be updated.
+ * @param fieldName the name of the field to be updated
* @return the updater
- * @throws IllegalArgumentException if the field is not a volatile reference type.
+ * @throws IllegalArgumentException if the field is not a volatile reference type
* @throws RuntimeException with a nested reflection-based
- * exception if the class does not hold field or is the wrong type.
+ * exception if the class does not hold field or is the wrong type,
+ * or the field is inaccessible to the caller according to Java language
+ * access control
*/
public static <U, W> AtomicReferenceFieldUpdater<U,W> newUpdater(Class<U> tclass, Class<W> vclass, String fieldName) {
return new AtomicReferenceFieldUpdaterImpl<U,W>(tclass,
@@ -82,7 +85,7 @@
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public abstract boolean compareAndSet(T obj, V expect, V update);
@@ -93,14 +96,14 @@
* other calls to {@code compareAndSet} and {@code set}, but not
* necessarily with respect to other changes in the field.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param obj An object whose field to conditionally set
* @param expect the expected value
* @param update the new value
- * @return true if successful.
+ * @return true if successful
*/
public abstract boolean weakCompareAndSet(T obj, V expect, V update);
@@ -169,23 +172,32 @@
* screenings fail.
*/
- AtomicReferenceFieldUpdaterImpl(Class<T> tclass,
+ AtomicReferenceFieldUpdaterImpl(final Class<T> tclass,
Class<V> vclass,
- String fieldName) {
- Field field = null;
- Class<?> fieldClass = null;
- Class<?> caller = null;
- int modifiers = 0;
+ final String fieldName) {
+ final Field field;
+ final Class<?> fieldClass;
+ final Class<?> caller;
+ final int modifiers;
try {
- field = tclass.getDeclaredField(fieldName);
+ field = tclass.getDeclaredField(fieldName); // android-changed
caller = VMStack.getStackClass2(); // android-changed
modifiers = field.getModifiers();
- // BEGIN android-removed
- // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
- // caller, tclass, null, modifiers);
- // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
- // END android-removed
+ // BEGIN android-removed
+ // sun.reflect.misc.ReflectUtil.ensureMemberAccess(
+ // caller, tclass, null, modifiers);
+ // ClassLoader cl = tclass.getClassLoader();
+ // ClassLoader ccl = caller.getClassLoader();
+ // if ((ccl != null) && (ccl != cl) &&
+ // ((cl == null) || !isAncestor(cl, ccl))) {
+ // sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
+ // }
+ // END android-removed
fieldClass = field.getType();
+ // BEGIN android-removed
+ // } catch (PrivilegedActionException pae) {
+ // throw new RuntimeException(pae.getException());
+ // END android-removed
} catch (Exception ex) {
throw new RuntimeException(ex);
}
@@ -206,6 +218,25 @@
offset = unsafe.objectFieldOffset(field);
}
+ // BEGIN android-removed
+ // /**
+ // * Returns true if the second classloader can be found in the first
+ // * classloader's delegation chain.
+ // * Equivalent to the inaccessible: first.isAncestor(second).
+ // */
+ //
+ // private static boolean isAncestor(ClassLoader first, ClassLoader second) {
+ // ClassLoader acl = first;
+ // do {
+ // acl = acl.getParent();
+ // if (second == acl) {
+ // return true;
+ // }
+ // } while (acl != null);
+ // return false;
+ // }
+ // END android-removed
+
void targetCheck(T obj) {
if (!tclass.isInstance(obj))
throw new ClassCastException();
@@ -254,6 +285,7 @@
unsafe.putOrderedObject(obj, offset, newValue);
}
+ @SuppressWarnings("unchecked")
public V get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null)
targetCheck(obj);
diff --git a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
index a0cb492..b93a6f3 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/AtomicStampedReference.java
@@ -83,9 +83,9 @@
* current reference is {@code ==} to the expected reference
* and the current stamp is equal to the expected stamp.
*
- * <p>May <a href="package-summary.html#Spurious">fail spuriously</a>
- * and does not provide ordering guarantees, so is only rarely an
- * appropriate alternative to {@code compareAndSet}.
+ * <p><a href="package-summary.html#weakCompareAndSet">May fail
+ * spuriously and does not provide ordering guarantees</a>, so is
+ * only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expectedReference the expected value of the reference
* @param newReference the new value for the reference
@@ -126,7 +126,6 @@
casPair(current, Pair.of(newReference, newStamp)));
}
-
/**
* Unconditionally sets the value of both the reference and stamp.
*
diff --git a/luni/src/main/java/java/util/concurrent/atomic/package-info.java b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
index efbb413..568d2c6 100644
--- a/luni/src/main/java/java/util/concurrent/atomic/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/atomic/package-info.java
@@ -54,19 +54,20 @@
*
* write your utility method as follows:
* <pre> {@code
- * boolean getAndTransform(AtomicLong var) {
+ * long getAndTransform(AtomicLong var) {
* while (true) {
* long current = var.get();
* long next = transform(current);
* if (var.compareAndSet(current, next))
* return current;
+ * // return next; for transformAndGet
* }
* }}</pre>
*
* <p>The memory effects for accesses and updates of atomics generally
* follow the rules for volatiles, as stated in
- * <a href="http://java.sun.com/docs/books/jls/"> The Java Language
- * Specification, Third Edition (17.4 Memory Model)</a>:
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
+ * The Java Language Specification (17.4 Memory Model)</a>:
*
* <ul>
*
@@ -122,13 +123,12 @@
* semantics for their array elements, which is not supported for
* ordinary arrays.
*
- * <a name="Spurious">
- * <p>The atomic classes also support method {@code weakCompareAndSet},
- * which has limited applicability. On some platforms, the weak version
- * may be more efficient than {@code compareAndSet} in the normal case,
- * but differs in that any given invocation of the
- * {@code weakCompareAndSet} method may return {@code false}
- * <em>spuriously</em> (that is, for no apparent reason)</a>. A
+ * <p id="weakCompareAndSet">The atomic classes also support method
+ * {@code weakCompareAndSet}, which has limited applicability. On some
+ * platforms, the weak version may be more efficient than {@code
+ * compareAndSet} in the normal case, but differs in that any given
+ * invocation of the {@code weakCompareAndSet} method may return {@code
+ * false} <em>spuriously</em> (that is, for no apparent reason). A
* {@code false} return means only that the operation may be retried if
* desired, relying on the guarantee that repeated invocation when the
* variable holds {@code expectedValue} and no other thread is also
@@ -164,7 +164,7 @@
*
* <p>Atomic classes are not general purpose replacements for
* {@code java.lang.Integer} and related classes. They do <em>not</em>
- * define methods such as {@code hashCode} and
+ * define methods such as {@code equals}, {@code hashCode} and
* {@code compareTo}. (Because atomic variables are expected to be
* mutated, they are poor choices for hash table keys.) Additionally,
* classes are provided only for those types that are commonly useful in
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
index 4bec0cf..fa01824 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractOwnableSynchronizer.java
@@ -10,7 +10,7 @@
* A synchronizer that may be exclusively owned by a thread. This
* class provides a basis for creating locks and related synchronizers
* that may entail a notion of ownership. The
- * <tt>AbstractOwnableSynchronizer</tt> class itself does not manage or
+ * {@code AbstractOwnableSynchronizer} class itself does not manage or
* use this information. However, subclasses and tools may use
* appropriately maintained values to help control and monitor access
* and provide diagnostics.
@@ -36,9 +36,9 @@
/**
* Sets the thread that currently owns exclusive access. A
- * <tt>null</tt> argument indicates that no thread owns access.
+ * {@code null} argument indicates that no thread owns access.
* This method does not otherwise impose any synchronization or
- * <tt>volatile</tt> field accesses.
+ * {@code volatile} field accesses.
*/
protected final void setExclusiveOwnerThread(Thread t) {
exclusiveOwnerThread = t;
@@ -46,9 +46,9 @@
/**
* Returns the thread last set by
- * <tt>setExclusiveOwnerThread</tt>, or <tt>null</tt> if never
+ * {@code setExclusiveOwnerThread}, or {@code null} if never
* set. This method does not otherwise impose any synchronization
- * or <tt>volatile</tt> field accesses.
+ * or {@code volatile} field accesses.
* @return the owner thread
*/
protected final Thread getExclusiveOwnerThread() {
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
index 7b36460..4c5e280 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java
@@ -5,17 +5,19 @@
*/
package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
import sun.misc.Unsafe;
/**
* A version of {@link AbstractQueuedSynchronizer} in
- * which synchronization state is maintained as a <tt>long</tt>.
+ * which synchronization state is maintained as a {@code long}.
* This class has exactly the same structure, properties, and methods
- * as <tt>AbstractQueuedSynchronizer</tt> with the exception
+ * as {@code AbstractQueuedSynchronizer} with the exception
* that all state-related parameters and results are defined
- * as <tt>long</tt> rather than <tt>int</tt>. This class
+ * as {@code long} rather than {@code int}. This class
* may be useful when creating synchronizers such as
* multilevel locks and barriers that require
* 64 bits of state.
@@ -40,7 +42,7 @@
*/
/**
- * Creates a new <tt>AbstractQueuedLongSynchronizer</tt> instance
+ * Creates a new {@code AbstractQueuedLongSynchronizer} instance
* with initial synchronization state of zero.
*/
protected AbstractQueuedLongSynchronizer() { }
@@ -73,7 +75,7 @@
*
* <p>Insertion into a CLH queue requires only a single atomic
* operation on "tail", so there is a simple atomic point of
- * demarcation from unqueued to queued. Similarly, dequeing
+ * demarcation from unqueued to queued. Similarly, dequeuing
* involves only updating the "head". However, it takes a bit
* more work for nodes to determine who their successors are,
* in part to deal with possible cancellation due to timeouts
@@ -180,7 +182,7 @@
/**
* Link to predecessor node that current node/thread relies on
- * for checking waitStatus. Assigned during enqueing, and nulled
+ * for checking waitStatus. Assigned during enqueuing, and nulled
* out (for sake of GC) only upon dequeuing. Also, upon
* cancellation of a predecessor, we short-circuit while
* finding a non-cancelled one, which will always exist
@@ -225,7 +227,7 @@
Node nextWaiter;
/**
- * Returns true if node is waiting in shared mode
+ * @return true if node is waiting in shared mode
*/
final boolean isShared() {
return nextWaiter == SHARED;
@@ -281,7 +283,7 @@
/**
* Returns the current value of synchronization state.
- * This operation has memory semantics of a <tt>volatile</tt> read.
+ * This operation has memory semantics of a {@code volatile} read.
* @return current state value
*/
protected final long getState() {
@@ -290,7 +292,7 @@
/**
* Sets the value of synchronization state.
- * This operation has memory semantics of a <tt>volatile</tt> write.
+ * This operation has memory semantics of a {@code volatile} write.
* @param newState the new state value
*/
protected final void setState(long newState) {
@@ -300,7 +302,7 @@
/**
* Atomically sets synchronization state to the given updated
* value if the current state value equals the expected value.
- * This operation has memory semantics of a <tt>volatile</tt> read
+ * This operation has memory semantics of a {@code volatile} read
* and write.
*
* @param expect the expected value
@@ -410,7 +412,7 @@
}
/**
- * Release action for shared mode -- signal successor and ensure
+ * Release action for shared mode -- signals successor and ensures
* propagation. (Note: For exclusive mode, release just amounts
* to calling unparkSuccessor of head if it needs signal.)
*/
@@ -531,7 +533,7 @@
/**
* Checks and updates status for a node that failed to acquire.
* Returns true if thread should block. This is the main signal
- * control in all acquire loops. Requires that pred == node.prev
+ * control in all acquire loops. Requires that pred == node.prev.
*
* @param pred node's predecessor holding status
* @param node the node
@@ -656,8 +658,10 @@
* @return {@code true} if acquired
*/
private boolean doAcquireNanos(long arg, long nanosTimeout)
- throws InterruptedException {
- long lastTime = System.nanoTime();
+ throws InterruptedException {
+ if (nanosTimeout <= 0L)
+ return false;
+ final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
@@ -669,14 +673,12 @@
failed = false;
return true;
}
- if (nanosTimeout <= 0)
+ nanosTimeout = deadline - System.nanoTime();
+ if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
if (Thread.interrupted())
throw new InterruptedException();
}
@@ -756,9 +758,10 @@
* @return {@code true} if acquired
*/
private boolean doAcquireSharedNanos(long arg, long nanosTimeout)
- throws InterruptedException {
-
- long lastTime = System.nanoTime();
+ throws InterruptedException {
+ if (nanosTimeout <= 0L)
+ return false;
+ final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
@@ -773,14 +776,12 @@
return true;
}
}
- if (nanosTimeout <= 0)
+ nanosTimeout = deadline - System.nanoTime();
+ if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
if (Thread.interrupted())
throw new InterruptedException();
}
@@ -1036,7 +1037,7 @@
* thread is queued, possibly repeatedly blocking and unblocking,
* invoking {@link #tryAcquireShared} until success or the thread
* is interrupted.
- * @param arg the acquire argument
+ * @param arg the acquire argument.
* This value is conveyed to {@link #tryAcquireShared} but is
* otherwise uninterpreted and can represent anything
* you like.
@@ -1254,8 +1255,9 @@
* current thread, and {@code false} if the current thread
* is at the head of the queue or the queue is empty
* @since 1.7
+ * @hide
*/
- /*public*/ final boolean hasQueuedPredecessors() { // android-changed
+ public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
@@ -1411,7 +1413,7 @@
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
- * cancelled before signal).
+ * cancelled before signal)
*/
final boolean transferForSignal(Node node) {
/*
@@ -1434,10 +1436,10 @@
}
/**
- * Transfers node, if necessary, to sync queue after a cancelled
- * wait. Returns true if thread was cancelled before being
- * signalled.
- * @param node its node
+ * Transfers node, if necessary, to sync queue after a cancelled wait.
+ * Returns true if thread was cancelled before being signalled.
+ *
+ * @param node the node
* @return true if cancelled before the node was signalled
*/
final boolean transferAfterCancelledWait(Node node) {
@@ -1485,25 +1487,23 @@
* uses this synchronizer as its lock.
*
* @param condition the condition
- * @return <tt>true</tt> if owned
+ * @return {@code true} if owned
* @throws NullPointerException if the condition is null
*/
public final boolean owns(ConditionObject condition) {
- if (condition == null)
- throw new NullPointerException();
return condition.isOwnedBy(this);
}
/**
* Queries whether any threads are waiting on the given condition
* associated with this synchronizer. Note that because timeouts
- * and interrupts may occur at any time, a <tt>true</tt> return
- * does not guarantee that a future <tt>signal</tt> will awaken
+ * and interrupts may occur at any time, a {@code true} return
+ * does not guarantee that a future {@code signal} will awaken
* any threads. This method is designed primarily for use in
* monitoring of the system state.
*
* @param condition the condition
- * @return <tt>true</tt> if there are any waiting threads
+ * @return {@code true} if there are any waiting threads
* @throws IllegalMonitorStateException if exclusive synchronization
* is not held
* @throws IllegalArgumentException if the given condition is
@@ -1570,7 +1570,7 @@
* and Condition users. Exported versions of this class will in
* general need to be accompanied by documentation describing
* condition semantics that rely on those of the associated
- * <tt>AbstractQueuedLongSynchronizer</tt>.
+ * {@code AbstractQueuedLongSynchronizer}.
*
* <p>This class is Serializable, but all fields are transient,
* so deserialized conditions have no waiters.
@@ -1585,7 +1585,7 @@
private transient Node lastWaiter;
/**
- * Creates a new <tt>ConditionObject</tt> instance.
+ * Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
@@ -1711,9 +1711,8 @@
* Implements uninterruptible condition wait.
* <ol>
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -1772,9 +1771,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled or interrupted.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -1805,9 +1803,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -1820,20 +1817,18 @@
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
- long lastTime = System.nanoTime();
+ final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
- LockSupport.parkNanos(this, nanosTimeout);
+ if (nanosTimeout >= spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
-
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
+ nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
@@ -1841,7 +1836,7 @@
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return nanosTimeout - (System.nanoTime() - lastTime);
+ return deadline - System.nanoTime();
}
/**
@@ -1849,9 +1844,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -1861,8 +1855,6 @@
*/
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
- if (deadline == null)
- throw new NullPointerException();
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
@@ -1893,9 +1885,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -1905,14 +1896,12 @@
*/
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
- if (unit == null)
- throw new NullPointerException();
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
long savedState = fullyRelease(node);
- long lastTime = System.nanoTime();
+ final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
@@ -1924,9 +1913,7 @@
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
+ nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
diff --git a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
index 42029f0..0350060 100644
--- a/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
+++ b/luni/src/main/java/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
@@ -5,8 +5,10 @@
*/
package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
import sun.misc.Unsafe;
// BEGIN android-note
@@ -18,12 +20,12 @@
* synchronizers (semaphores, events, etc) that rely on
* first-in-first-out (FIFO) wait queues. This class is designed to
* be a useful basis for most kinds of synchronizers that rely on a
- * single atomic <tt>int</tt> value to represent state. Subclasses
+ * single atomic {@code int} value to represent state. Subclasses
* must define the protected methods that change this state, and which
* define what that state means in terms of this object being acquired
* or released. Given these, the other methods in this class carry
* out all queuing and blocking mechanics. Subclasses can maintain
- * other state fields, but only the atomically updated <tt>int</tt>
+ * other state fields, but only the atomically updated {@code int}
* value manipulated using methods {@link #getState}, {@link
* #setState} and {@link #compareAndSetState} is tracked with respect
* to synchronization.
@@ -31,7 +33,7 @@
* <p>Subclasses should be defined as non-public internal helper
* classes that are used to implement the synchronization properties
* of their enclosing class. Class
- * <tt>AbstractQueuedSynchronizer</tt> does not implement any
+ * {@code AbstractQueuedSynchronizer} does not implement any
* synchronization interface. Instead it defines methods such as
* {@link #acquireInterruptibly} that can be invoked as
* appropriate by concrete locks and related synchronizers to
@@ -58,7 +60,7 @@
* invoked with the current {@link #getState} value fully releases
* this object, and {@link #acquire}, given this saved state value,
* eventually restores this object to its previous acquired state. No
- * <tt>AbstractQueuedSynchronizer</tt> method otherwise creates such a
+ * {@code AbstractQueuedSynchronizer} method otherwise creates such a
* condition, so if this constraint cannot be met, do not use it. The
* behavior of {@link ConditionObject} depends of course on the
* semantics of its synchronizer implementation.
@@ -66,13 +68,13 @@
* <p>This class provides inspection, instrumentation, and monitoring
* methods for the internal queue, as well as similar methods for
* condition objects. These can be exported as desired into classes
- * using an <tt>AbstractQueuedSynchronizer</tt> for their
+ * using an {@code AbstractQueuedSynchronizer} for their
* synchronization mechanics.
*
* <p>Serialization of this class stores only the underlying atomic
* integer maintaining state, so deserialized objects have empty
* thread queues. Typical subclasses requiring serializability will
- * define a <tt>readObject</tt> method that restores this to a known
+ * define a {@code readObject} method that restores this to a known
* initial state upon deserialization.
*
* <h3>Usage</h3>
@@ -88,14 +90,14 @@
* <li> {@link #tryAcquireShared}
* <li> {@link #tryReleaseShared}
* <li> {@link #isHeldExclusively}
- *</ul>
+ * </ul>
*
* Each of these methods by default throws {@link
* UnsupportedOperationException}. Implementations of these methods
* must be internally thread-safe, and should in general be short and
* not block. Defining these methods is the <em>only</em> supported
* means of using this class. All other methods are declared
- * <tt>final</tt> because they cannot be independently varied.
+ * {@code final} because they cannot be independently varied.
*
* <p>You may also find the inherited methods from {@link
* AbstractOwnableSynchronizer} useful to keep track of the thread
@@ -121,19 +123,19 @@
*
* (Shared mode is similar but may involve cascading signals.)
*
- * <p><a name="barging">Because checks in acquire are invoked before
+ * <p id="barging">Because checks in acquire are invoked before
* enqueuing, a newly acquiring thread may <em>barge</em> ahead of
- * others that are blocked and queued. However, you can, if desired,
- * define <tt>tryAcquire</tt> and/or <tt>tryAcquireShared</tt> to
+ * others that are blocked and queued. However, you can, if desired,
+ * define {@code tryAcquire} and/or {@code tryAcquireShared} to
* disable barging by internally invoking one or more of the inspection
* methods. In particular, a strict FIFO lock can define
- * <tt>tryAcquire</tt> to immediately return <tt>false</tt> if {@link
+ * {@code tryAcquire} to immediately return {@code false} if {@link
* #getFirstQueuedThread} does not return the current thread. A
* normally preferable non-strict fair version can immediately return
- * <tt>false</tt> only if {@link #hasQueuedThreads} returns
- * <tt>true</tt> and <tt>getFirstQueuedThread</tt> is not the current
- * thread; or equivalently, that <tt>getFirstQueuedThread</tt> is both
- * non-null and not the current thread. Further variations are
+ * {@code false} only if {@link #hasQueuedThreads} returns
+ * {@code true} and {@code getFirstQueuedThread} is not the current
+ * thread; or equivalently, that {@code getFirstQueuedThread} is both
+ * non-null and not the current thread. Further variations are
* possible.
*
* <p>Throughput and scalability are generally highest for the
@@ -144,7 +146,7 @@
* threads, and each recontention has an unbiased chance to succeed
* against incoming threads. Also, while acquires do not
* "spin" in the usual sense, they may perform multiple
- * invocations of <tt>tryAcquire</tt> interspersed with other
+ * invocations of {@code tryAcquire} interspersed with other
* computations before blocking. This gives most of the benefits of
* spins when exclusive synchronization is only briefly held, without
* most of the liabilities when it isn't. If so desired, you can
@@ -155,7 +157,7 @@
*
* <p>This class provides an efficient and scalable basis for
* synchronization in part by specializing its range of use to
- * synchronizers that can rely on <tt>int</tt> state, acquire, and
+ * synchronizers that can rely on {@code int} state, acquire, and
* release parameters, and an internal FIFO wait queue. When this does
* not suffice, you can build synchronizers from a lower level using
* {@link java.util.concurrent.atomic atomic} classes, your own custom
@@ -177,12 +179,12 @@
*
* // Our internal helper class
* private static class Sync extends AbstractQueuedSynchronizer {
- * // Report whether in locked state
+ * // Reports whether in locked state
* protected boolean isHeldExclusively() {
* return getState() == 1;
* }
*
- * // Acquire the lock if state is zero
+ * // Acquires the lock if state is zero
* public boolean tryAcquire(int acquires) {
* assert acquires == 1; // Otherwise unused
* if (compareAndSetState(0, 1)) {
@@ -192,7 +194,7 @@
* return false;
* }
*
- * // Release the lock by setting state to zero
+ * // Releases the lock by setting state to zero
* protected boolean tryRelease(int releases) {
* assert releases == 1; // Otherwise unused
* if (getState() == 0) throw new IllegalMonitorStateException();
@@ -201,10 +203,10 @@
* return true;
* }
*
- * // Provide a Condition
+ * // Provides a Condition
* Condition newCondition() { return new ConditionObject(); }
*
- * // Deserialize properly
+ * // Deserializes properly
* private void readObject(ObjectInputStream s)
* throws IOException, ClassNotFoundException {
* s.defaultReadObject();
@@ -230,9 +232,10 @@
* }
* }}</pre>
*
- * <p>Here is a latch class that is like a {@link CountDownLatch}
- * except that it only requires a single <tt>signal</tt> to
- * fire. Because a latch is non-exclusive, it uses the <tt>shared</tt>
+ * <p>Here is a latch class that is like a
+ * {@link java.util.concurrent.CountDownLatch CountDownLatch}
+ * except that it only requires a single {@code signal} to
+ * fire. Because a latch is non-exclusive, it uses the {@code shared}
* acquire and release methods.
*
* <pre> {@code
@@ -269,7 +272,7 @@
private static final long serialVersionUID = 7373984972572414691L;
/**
- * Creates a new <tt>AbstractQueuedSynchronizer</tt> instance
+ * Creates a new {@code AbstractQueuedSynchronizer} instance
* with initial synchronization state of zero.
*/
protected AbstractQueuedSynchronizer() { }
@@ -302,7 +305,7 @@
*
* <p>Insertion into a CLH queue requires only a single atomic
* operation on "tail", so there is a simple atomic point of
- * demarcation from unqueued to queued. Similarly, dequeing
+ * demarcation from unqueued to queued. Similarly, dequeuing
* involves only updating the "head". However, it takes a bit
* more work for nodes to determine who their successors are,
* in part to deal with possible cancellation due to timeouts
@@ -409,7 +412,7 @@
/**
* Link to predecessor node that current node/thread relies on
- * for checking waitStatus. Assigned during enqueing, and nulled
+ * for checking waitStatus. Assigned during enqueuing, and nulled
* out (for sake of GC) only upon dequeuing. Also, upon
* cancellation of a predecessor, we short-circuit while
* finding a non-cancelled one, which will always exist
@@ -454,7 +457,7 @@
Node nextWaiter;
/**
- * Returns true if node is waiting in shared mode
+ * Returns true if node is waiting in shared mode.
*/
final boolean isShared() {
return nextWaiter == SHARED;
@@ -510,7 +513,7 @@
/**
* Returns the current value of synchronization state.
- * This operation has memory semantics of a <tt>volatile</tt> read.
+ * This operation has memory semantics of a {@code volatile} read.
* @return current state value
*/
protected final int getState() {
@@ -519,7 +522,7 @@
/**
* Sets the value of synchronization state.
- * This operation has memory semantics of a <tt>volatile</tt> write.
+ * This operation has memory semantics of a {@code volatile} write.
* @param newState the new state value
*/
protected final void setState(int newState) {
@@ -529,7 +532,7 @@
/**
* Atomically sets synchronization state to the given updated
* value if the current state value equals the expected value.
- * This operation has memory semantics of a <tt>volatile</tt> read
+ * This operation has memory semantics of a {@code volatile} read
* and write.
*
* @param expect the expected value
@@ -639,7 +642,7 @@
}
/**
- * Release action for shared mode -- signal successor and ensure
+ * Release action for shared mode -- signals successor and ensures
* propagation. (Note: For exclusive mode, release just amounts
* to calling unparkSuccessor of head if it needs signal.)
*/
@@ -760,7 +763,7 @@
/**
* Checks and updates status for a node that failed to acquire.
* Returns true if thread should block. This is the main signal
- * control in all acquire loops. Requires that pred == node.prev
+ * control in all acquire loops. Requires that pred == node.prev.
*
* @param pred node's predecessor holding status
* @param node the node
@@ -885,8 +888,10 @@
* @return {@code true} if acquired
*/
private boolean doAcquireNanos(int arg, long nanosTimeout)
- throws InterruptedException {
- long lastTime = System.nanoTime();
+ throws InterruptedException {
+ if (nanosTimeout <= 0L)
+ return false;
+ final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.EXCLUSIVE);
boolean failed = true;
try {
@@ -898,14 +903,12 @@
failed = false;
return true;
}
- if (nanosTimeout <= 0)
+ nanosTimeout = deadline - System.nanoTime();
+ if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
if (Thread.interrupted())
throw new InterruptedException();
}
@@ -985,9 +988,10 @@
* @return {@code true} if acquired
*/
private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
- throws InterruptedException {
-
- long lastTime = System.nanoTime();
+ throws InterruptedException {
+ if (nanosTimeout <= 0L)
+ return false;
+ final long deadline = System.nanoTime() + nanosTimeout;
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
@@ -1002,14 +1006,12 @@
return true;
}
}
- if (nanosTimeout <= 0)
+ nanosTimeout = deadline - System.nanoTime();
+ if (nanosTimeout <= 0L)
return false;
if (shouldParkAfterFailedAcquire(p, node) &&
nanosTimeout > spinForTimeoutThreshold)
LockSupport.parkNanos(this, nanosTimeout);
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
if (Thread.interrupted())
throw new InterruptedException();
}
@@ -1265,7 +1267,7 @@
* thread is queued, possibly repeatedly blocking and unblocking,
* invoking {@link #tryAcquireShared} until success or the thread
* is interrupted.
- * @param arg the acquire argument
+ * @param arg the acquire argument.
* This value is conveyed to {@link #tryAcquireShared} but is
* otherwise uninterpreted and can represent anything
* you like.
@@ -1641,7 +1643,7 @@
* Returns true if successful.
* @param node the node
* @return true if successfully transferred (else the node was
- * cancelled before signal).
+ * cancelled before signal)
*/
final boolean transferForSignal(Node node) {
/*
@@ -1664,10 +1666,10 @@
}
/**
- * Transfers node, if necessary, to sync queue after a cancelled
- * wait. Returns true if thread was cancelled before being
- * signalled.
- * @param node its node
+ * Transfers node, if necessary, to sync queue after a cancelled wait.
+ * Returns true if thread was cancelled before being signalled.
+ *
+ * @param node the node
* @return true if cancelled before the node was signalled
*/
final boolean transferAfterCancelledWait(Node node) {
@@ -1715,25 +1717,23 @@
* uses this synchronizer as its lock.
*
* @param condition the condition
- * @return <tt>true</tt> if owned
+ * @return {@code true} if owned
* @throws NullPointerException if the condition is null
*/
public final boolean owns(ConditionObject condition) {
- if (condition == null)
- throw new NullPointerException();
return condition.isOwnedBy(this);
}
/**
* Queries whether any threads are waiting on the given condition
* associated with this synchronizer. Note that because timeouts
- * and interrupts may occur at any time, a <tt>true</tt> return
- * does not guarantee that a future <tt>signal</tt> will awaken
+ * and interrupts may occur at any time, a {@code true} return
+ * does not guarantee that a future {@code signal} will awaken
* any threads. This method is designed primarily for use in
* monitoring of the system state.
*
* @param condition the condition
- * @return <tt>true</tt> if there are any waiting threads
+ * @return {@code true} if there are any waiting threads
* @throws IllegalMonitorStateException if exclusive synchronization
* is not held
* @throws IllegalArgumentException if the given condition is
@@ -1800,7 +1800,7 @@
* and Condition users. Exported versions of this class will in
* general need to be accompanied by documentation describing
* condition semantics that rely on those of the associated
- * <tt>AbstractQueuedSynchronizer</tt>.
+ * {@code AbstractQueuedSynchronizer}.
*
* <p>This class is Serializable, but all fields are transient,
* so deserialized conditions have no waiters.
@@ -1813,7 +1813,7 @@
private transient Node lastWaiter;
/**
- * Creates a new <tt>ConditionObject</tt> instance.
+ * Creates a new {@code ConditionObject} instance.
*/
public ConditionObject() { }
@@ -1939,9 +1939,8 @@
* Implements uninterruptible condition wait.
* <ol>
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -2000,9 +1999,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled or interrupted.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -2033,9 +2031,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -2048,20 +2045,18 @@
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
- long lastTime = System.nanoTime();
+ final long deadline = System.nanoTime() + nanosTimeout;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
if (nanosTimeout <= 0L) {
transferAfterCancelledWait(node);
break;
}
- LockSupport.parkNanos(this, nanosTimeout);
+ if (nanosTimeout >= spinForTimeoutThreshold)
+ LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
-
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
+ nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
@@ -2069,7 +2064,7 @@
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
- return nanosTimeout - (System.nanoTime() - lastTime);
+ return deadline - System.nanoTime();
}
/**
@@ -2077,9 +2072,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -2089,8 +2083,6 @@
*/
public final boolean awaitUntil(Date deadline)
throws InterruptedException {
- if (deadline == null)
- throw new NullPointerException();
long abstime = deadline.getTime();
if (Thread.interrupted())
throw new InterruptedException();
@@ -2121,9 +2113,8 @@
* <ol>
* <li> If current thread is interrupted, throw InterruptedException.
* <li> Save lock state returned by {@link #getState}.
- * <li> Invoke {@link #release} with
- * saved state as argument, throwing
- * IllegalMonitorStateException if it fails.
+ * <li> Invoke {@link #release} with saved state as argument,
+ * throwing IllegalMonitorStateException if it fails.
* <li> Block until signalled, interrupted, or timed out.
* <li> Reacquire by invoking specialized version of
* {@link #acquire} with saved state as argument.
@@ -2133,14 +2124,12 @@
*/
public final boolean await(long time, TimeUnit unit)
throws InterruptedException {
- if (unit == null)
- throw new NullPointerException();
long nanosTimeout = unit.toNanos(time);
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
- long lastTime = System.nanoTime();
+ final long deadline = System.nanoTime() + nanosTimeout;
boolean timedout = false;
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
@@ -2152,9 +2141,7 @@
LockSupport.parkNanos(this, nanosTimeout);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
- long now = System.nanoTime();
- nanosTimeout -= now - lastTime;
- lastTime = now;
+ nanosTimeout = deadline - System.nanoTime();
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
diff --git a/luni/src/main/java/java/util/concurrent/locks/Condition.java b/luni/src/main/java/java/util/concurrent/locks/Condition.java
index 7050df9..522e9e2 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Condition.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Condition.java
@@ -5,7 +5,7 @@
*/
package java.util.concurrent.locks;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
import java.util.Date;
/**
@@ -295,7 +295,7 @@
* }
* }}</pre>
*
- * <p> Design note: This method requires a nanosecond argument so
+ * <p>Design note: This method requires a nanosecond argument so
* as to avoid truncation errors in reporting remaining times.
* Such precision loss would make it difficult for programmers to
* ensure that total waiting times are not systematically shorter
diff --git a/luni/src/main/java/java/util/concurrent/locks/Lock.java b/luni/src/main/java/java/util/concurrent/locks/Lock.java
index d5c6294..6eeb236 100644
--- a/luni/src/main/java/java/util/concurrent/locks/Lock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/Lock.java
@@ -91,8 +91,9 @@
*
* <p>All {@code Lock} implementations <em>must</em> enforce the same
* memory synchronization semantics as provided by the built-in monitor
- * lock, as described in <a href="http://java.sun.com/docs/books/jls/">
- * The Java Language Specification, Third Edition (17.4 Memory Model)</a>:
+ * lock, as described in
+ * <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4">
+ * The Java Language Specification (17.4 Memory Model)</a>:
* <ul>
* <li>A successful {@code lock} operation has the same memory
* synchronization effects as a successful <em>Lock</em> action.
@@ -106,7 +107,7 @@
*
* <h3>Implementation Considerations</h3>
*
- * <p> The three forms of lock acquisition (interruptible,
+ * <p>The three forms of lock acquisition (interruptible,
* non-interruptible, and timed) may differ in their performance
* characteristics, ordering guarantees, or other implementation
* qualities. Further, the ability to interrupt the <em>ongoing</em>
@@ -197,7 +198,7 @@
*
* @throws InterruptedException if the current thread is
* interrupted while acquiring the lock (and interruption
- * of lock acquisition is supported).
+ * of lock acquisition is supported)
*/
void lockInterruptibly() throws InterruptedException;
diff --git a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
index 422e428..875b2bf 100644
--- a/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
+++ b/luni/src/main/java/java/util/concurrent/locks/LockSupport.java
@@ -7,7 +7,6 @@
package java.util.concurrent.locks;
import sun.misc.Unsafe;
-
/**
* Basic thread blocking primitives for creating locks and other
* synchronization classes.
@@ -73,14 +72,14 @@
* // Block while not first in queue or cannot acquire lock
* while (waiters.peek() != current ||
* !locked.compareAndSet(false, true)) {
- * LockSupport.park(this);
- * if (Thread.interrupted()) // ignore interrupts while waiting
- * wasInterrupted = true;
+ * LockSupport.park(this);
+ * if (Thread.interrupted()) // ignore interrupts while waiting
+ * wasInterrupted = true;
* }
*
* waiters.remove();
* if (wasInterrupted) // reassert interrupt status on exit
- * current.interrupt();
+ * current.interrupt();
* }
*
* public void unlock() {
@@ -89,7 +88,6 @@
* }
* }}</pre>
*/
-
public class LockSupport {
private LockSupport() {} // Cannot be instantiated.
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
index bb7b388..8690355 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReadWriteLock.java
@@ -7,16 +7,16 @@
package java.util.concurrent.locks;
/**
- * A <tt>ReadWriteLock</tt> maintains a pair of associated {@link
+ * A {@code ReadWriteLock} maintains a pair of associated {@link
* Lock locks}, one for read-only operations and one for writing.
* The {@link #readLock read lock} may be held simultaneously by
* multiple reader threads, so long as there are no writers. The
* {@link #writeLock write lock} is exclusive.
*
- * <p>All <tt>ReadWriteLock</tt> implementations must guarantee that
- * the memory synchronization effects of <tt>writeLock</tt> operations
+ * <p>All {@code ReadWriteLock} implementations must guarantee that
+ * the memory synchronization effects of {@code writeLock} operations
* (as specified in the {@link Lock} interface) also hold with respect
- * to the associated <tt>readLock</tt>. That is, a thread successfully
+ * to the associated {@code readLock}. That is, a thread successfully
* acquiring the read lock will see all updates made upon previous
* release of the write lock.
*
@@ -91,14 +91,14 @@
/**
* Returns the lock used for reading.
*
- * @return the lock used for reading.
+ * @return the lock used for reading
*/
Lock readLock();
/**
* Returns the lock used for writing.
*
- * @return the lock used for writing.
+ * @return the lock used for writing
*/
Lock writeLock();
}
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
index 07baf41..bde4741 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantLock.java
@@ -5,8 +5,8 @@
*/
package java.util.concurrent.locks;
-import java.util.*;
-import java.util.concurrent.*;
+import java.util.concurrent.TimeUnit;
+import java.util.Collection;
/**
* A reentrant mutual exclusion {@link Lock} with the same basic
@@ -35,7 +35,7 @@
* fair lock may obtain it multiple times in succession while other
* active threads are not progressing and not currently holding the
* lock.
- * Also note that the untimed {@link #tryLock() tryLock} method does not
+ * Also note that the untimed {@link #tryLock()} method does not
* honor the fairness setting. It will succeed if the lock
* is available even if other threads are waiting.
*
@@ -59,10 +59,9 @@
* }}</pre>
*
* <p>In addition to implementing the {@link Lock} interface, this
- * class defines methods {@code isLocked} and
- * {@code getLockQueueLength}, as well as some associated
- * {@code protected} access methods that may be useful for
- * instrumentation and monitoring.
+ * class defines a number of {@code public} and {@code protected}
+ * methods for inspecting the state of the lock. Some of these
+ * methods are only useful for instrumentation and monitoring.
*
* <p>Serialization of this class behaves in the same way as built-in
* locks: a deserialized lock is in the unlocked state, regardless of
@@ -95,9 +94,8 @@
abstract void lock();
/**
- * Performs non-fair tryLock. tryAcquire is
- * implemented in subclasses, but both need nonfair
- * try for trylock method.
+ * Performs non-fair tryLock. tryAcquire is implemented in
+ * subclasses, but both need nonfair try for trylock method.
*/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
@@ -156,8 +154,7 @@
}
/**
- * Reconstitutes this lock instance from a stream.
- * @param s the stream
+ * Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -325,7 +322,7 @@
* {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
* which is almost equivalent (it also detects interruption).
*
- * <p> If the current thread already holds this lock then the hold
+ * <p>If the current thread already holds this lock then the hold
* count is incremented by one and the method returns {@code true}.
*
* <p>If the lock is held by another thread then this method will return
@@ -410,7 +407,6 @@
* the lock could be acquired
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if the time unit is null
- *
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
@@ -605,7 +601,6 @@
return sync.hasQueuedThreads();
}
-
/**
* Queries whether the given thread is waiting to acquire this
* lock. Note that because cancellations may occur at any time, a
@@ -621,7 +616,6 @@
return sync.isQueued(thread);
}
-
/**
* Returns an estimate of the number of threads waiting to
* acquire this lock. The value is only an estimate because the number of
diff --git a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
index 244a4a7..2d3c65d 100644
--- a/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
+++ b/luni/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
@@ -5,8 +5,8 @@
*/
package java.util.concurrent.locks;
-import java.util.concurrent.*;
-import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.Collection;
/**
* An implementation of {@link ReadWriteLock} supporting similar
@@ -16,7 +16,7 @@
* <ul>
* <li><b>Acquisition order</b>
*
- * <p> This class does not impose a reader or writer preference
+ * <p>This class does not impose a reader or writer preference
* ordering for lock access. However, it does support an optional
* <em>fairness</em> policy.
*
@@ -30,7 +30,7 @@
* <p>
*
* <dt><b><i>Fair mode</i></b>
- * <dd> When constructed as fair, threads contend for entry using an
+ * <dd>When constructed as fair, threads contend for entry using an
* approximately arrival-order policy. When the currently held lock
* is released, either the longest-waiting single writer thread will
* be assigned the write lock, or if there is a group of reader threads
@@ -183,7 +183,6 @@
*
* @since 1.5
* @author Doug Lea
- *
*/
public class ReentrantReadWriteLock
implements ReadWriteLock, java.io.Serializable {
@@ -624,10 +623,7 @@
}
/**
- * Reconstitutes this lock instance from a stream (that is,
- * deserializes it).
- *
- * @param s the stream
+ * Reconstitutes the instance from a stream (that is, deserializes it).
*/
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
@@ -771,7 +767,7 @@
*
* @return {@code true} if the read lock was acquired
*/
- public boolean tryLock() {
+ public boolean tryLock() {
return sync.tryReadLock();
}
@@ -841,7 +837,6 @@
* @return {@code true} if the read lock was acquired
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if the time unit is null
- *
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
@@ -851,10 +846,10 @@
/**
* Attempts to release this lock.
*
- * <p> If the number of readers is now zero then the lock
+ * <p>If the number of readers is now zero then the lock
* is made available for write lock attempts.
*/
- public void unlock() {
+ public void unlock() {
sync.releaseShared(1);
}
@@ -993,7 +988,7 @@
* #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
* which is almost equivalent (it also detects interruption).
*
- * <p> If the current thread already holds this lock then the
+ * <p>If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
* {@code true}.
*
@@ -1086,7 +1081,6 @@
*
* @throws InterruptedException if the current thread is interrupted
* @throws NullPointerException if the time unit is null
- *
*/
public boolean tryLock(long timeout, TimeUnit unit)
throws InterruptedException {
@@ -1103,7 +1097,7 @@
* IllegalMonitorStateException} is thrown.
*
* @throws IllegalMonitorStateException if the current thread does not
- * hold this lock.
+ * hold this lock
*/
public void unlock() {
sync.release(1);
@@ -1231,7 +1225,7 @@
* Queries the number of read locks held for this lock. This
* method is designed for use in monitoring system state, not for
* synchronization control.
- * @return the number of read locks held.
+ * @return the number of read locks held
*/
public int getReadLockCount() {
return sync.getReadLockCount();
diff --git a/luni/src/main/java/java/util/concurrent/package-info.java b/luni/src/main/java/java/util/concurrent/package-info.java
index 155d1b8..51a29e8 100644
--- a/luni/src/main/java/java/util/concurrent/package-info.java
+++ b/luni/src/main/java/java/util/concurrent/package-info.java
@@ -5,7 +5,7 @@
*/
// BEGIN android-note
-// omit links to ForkJoinPool, ForkJoinTask, LinkedTransferQueue, PHaser, TransferQueue
+// omit links to ForkJoinPool, ForkJoinTask, LinkedTransferQueue, Phaser, TransferQueue
// END android-note
/**
@@ -23,7 +23,7 @@
*
* {@link java.util.concurrent.Executor} is a simple standardized
* interface for defining custom thread-like subsystems, including
- * thread pools, asynchronous IO, and lightweight task frameworks.
+ * thread pools, asynchronous I/O, and lightweight task frameworks.
* Depending on which concrete Executor class is being used, tasks may
* execute in a newly created thread, an existing task-execution thread,
* or the thread calling {@link java.util.concurrent.Executor#execute
@@ -174,7 +174,7 @@
* it may (or may not) reflect any updates since the iterator was
* created.
*
- * <h2><a name="MemoryVisibility">Memory Consistency Properties</a></h2>
+ * <h2 id="MemoryVisibility">Memory Consistency Properties</h2>
*
* <a href="http://java.sun.com/docs/books/jls/third_edition/html/memory.html">
* Chapter 17 of the Java Language Specification</a> defines the
@@ -243,8 +243,7 @@
* in each thread <i>happen-before</i> those subsequent to the
* corresponding {@code exchange()} in another thread.
*
- * <li>Actions prior to calling {@code CyclicBarrier.await} and
- * {@code Phaser.awaitAdvance} (as well as its variants)
+ * <li>Actions prior to calling {@code CyclicBarrier.await}
* <i>happen-before</i> actions performed by the barrier action, and
* actions performed by the barrier action <i>happen-before</i> actions
* subsequent to a successful return from the corresponding {@code await}
diff --git a/luni/src/main/java/java/util/jar/Attributes.java b/luni/src/main/java/java/util/jar/Attributes.java
index 48008ce..7e32897 100644
--- a/luni/src/main/java/java/util/jar/Attributes.java
+++ b/luni/src/main/java/java/util/jar/Attributes.java
@@ -50,8 +50,6 @@
* </pre>
*/
public static class Name {
- private final String name;
-
/** The class path (a main attribute). */
public static final Name CLASS_PATH = new Name("Class-Path");
@@ -140,7 +138,12 @@
*/
public static final Name IMPLEMENTATION_URL = new Name("Implementation-URL");
- static final Name NAME = new Name("Name");
+ /**
+ * @hide
+ */
+ public static final Name NAME = new Name("Name");
+
+ private final String name;
public Name(String name) {
// encoded name + "\r\n" must be <= 72 bytes; ASCII-only so byte count equals char count
@@ -409,20 +412,16 @@
* valid key.
*/
public String getValue(String name) {
- return (String) map.get(new Attributes.Name(name));
+ return getValue(new Attributes.Name(name));
}
/**
- * Stores the value {@code val} associated with the key {@code name} in this
+ * Stores the value {@code value} associated with the key {@code name} in this
* {@code Attributes}.
*
- * @param name
- * the key to store.
- * @param val
- * the value to store in this {@code Attributes}.
* @return the value being stored.
*/
- public String putValue(String name, String val) {
- return (String) map.put(new Attributes.Name(name), val);
+ public String putValue(String name, String value) {
+ return (String) map.put(new Attributes.Name(name), value);
}
}
diff --git a/luni/src/main/java/java/util/jar/JarFile.java b/luni/src/main/java/java/util/jar/JarFile.java
index 178688f..5293a89 100644
--- a/luni/src/main/java/java/util/jar/JarFile.java
+++ b/luni/src/main/java/java/util/jar/JarFile.java
@@ -98,18 +98,18 @@
}
@Override
- public int read(byte[] buf, int off, int nbytes) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (done) {
return -1;
}
if (count > 0) {
- int r = super.read(buf, off, nbytes);
+ int r = super.read(buffer, byteOffset, byteCount);
if (r != -1) {
int size = r;
if (count < size) {
size = (int) count;
}
- entry.write(buf, off, size);
+ entry.write(buffer, byteOffset, size);
count -= size;
} else {
count = 0;
diff --git a/luni/src/main/java/java/util/jar/JarInputStream.java b/luni/src/main/java/java/util/jar/JarInputStream.java
index 03f765f..5e08b5d 100644
--- a/luni/src/main/java/java/util/jar/JarInputStream.java
+++ b/luni/src/main/java/java/util/jar/JarInputStream.java
@@ -130,25 +130,18 @@
}
/**
- * Reads up to {@code length} of decompressed data and stores it in
- * {@code buffer} starting at {@code offset}.
+ * Reads up to {@code byteCount} bytes of decompressed data and stores it in
+ * {@code buffer} starting at {@code byteOffset}. Returns the number of uncompressed bytes read.
*
- * @param buffer
- * Buffer to store into
- * @param offset
- * offset in buffer to store at
- * @param length
- * number of bytes to store
- * @return Number of uncompressed bytes read
* @throws IOException
* if an IOException occurs.
*/
@Override
- public int read(byte[] buffer, int offset, int length) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (mEntry != null) {
return -1;
}
- int r = super.read(buffer, offset, length);
+ int r = super.read(buffer, byteOffset, byteCount);
if (verStream != null && !eos) {
if (r == -1) {
eos = true;
@@ -168,7 +161,7 @@
}
}
} else {
- verStream.write(buffer, offset, r);
+ verStream.write(buffer, byteOffset, r);
}
}
return r;
diff --git a/luni/src/main/java/java/util/jar/JarVerifier.java b/luni/src/main/java/java/util/jar/JarVerifier.java
index 5e3dd76..8185c6d 100644
--- a/luni/src/main/java/java/util/jar/JarVerifier.java
+++ b/luni/src/main/java/java/util/jar/JarVerifier.java
@@ -20,7 +20,7 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -219,7 +219,7 @@
if (hash == null) {
continue;
}
- byte[] hashBytes = hash.getBytes(Charsets.ISO_8859_1);
+ byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
try {
return new VerifierEntry(name, MessageDigest.getInstance(algorithm), hashBytes,
@@ -289,8 +289,7 @@
*/
private void verifyCertificate(String certFile) {
// Found Digital Sig, .SF should already have been read
- String signatureFile = certFile.substring(0, certFile.lastIndexOf('.'))
- + ".SF";
+ String signatureFile = certFile.substring(0, certFile.lastIndexOf('.')) + ".SF";
byte[] sfBytes = metaEntries.get(signatureFile);
if (sfBytes == null) {
return;
@@ -328,8 +327,8 @@
Attributes attributes = new Attributes();
HashMap<String, Attributes> entries = new HashMap<String, Attributes>();
try {
- InitManifest im = new InitManifest(sfBytes, attributes);
- im.initEntries(entries, null);
+ ManifestReader im = new ManifestReader(sfBytes, attributes);
+ im.readEntries(entries, null);
} catch (IOException e) {
return;
}
@@ -357,12 +356,9 @@
}
// Use .SF to verify the whole manifest.
- String digestAttribute = createdBySigntool ? "-Digest"
- : "-Digest-Manifest";
- if (!verify(attributes, digestAttribute, manifest, 0, manifest.length,
- false, false)) {
- Iterator<Map.Entry<String, Attributes>> it = entries.entrySet()
- .iterator();
+ String digestAttribute = createdBySigntool ? "-Digest" : "-Digest-Manifest";
+ if (!verify(attributes, digestAttribute, manifest, 0, manifest.length, false, false)) {
+ Iterator<Map.Entry<String, Attributes>> it = entries.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, Attributes> entry = it.next();
Manifest.Chunk chunk = man.getChunk(entry.getKey());
@@ -415,14 +411,13 @@
} catch (NoSuchAlgorithmException e) {
continue;
}
- if (ignoreSecondEndline && data[end - 1] == '\n'
- && data[end - 2] == '\n') {
+ if (ignoreSecondEndline && data[end - 1] == '\n' && data[end - 2] == '\n') {
md.update(data, start, end - 1 - start);
} else {
md.update(data, start, end - start);
}
byte[] b = md.digest();
- byte[] hashBytes = hash.getBytes(Charsets.ISO_8859_1);
+ byte[] hashBytes = hash.getBytes(StandardCharsets.ISO_8859_1);
return MessageDigest.isEqual(b, Base64.decode(hashBytes));
}
return ignorable;
diff --git a/luni/src/main/java/java/util/jar/Manifest.java b/luni/src/main/java/java/util/jar/Manifest.java
index 723aa99..b6ebddc 100644
--- a/luni/src/main/java/java/util/jar/Manifest.java
+++ b/luni/src/main/java/java/util/jar/Manifest.java
@@ -25,8 +25,8 @@
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharsetEncoder;
-import java.nio.charset.Charsets;
import java.nio.charset.CoderResult;
+import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -43,8 +43,6 @@
private static final byte[] VALUE_SEPARATOR = new byte[] { ':', ' ' };
- private static final Attributes.Name NAME_ATTRIBUTE = new Attributes.Name("Name");
-
private static final Field BAIS_BUF = getByteArrayInputStreamField("buf");
private static final Field BAIS_POS = getByteArrayInputStreamField("pos");
@@ -213,9 +211,9 @@
buf[buf.length - 1] = '\n';
}
- InitManifest im = new InitManifest(buf, mainAttributes);
- mainEnd = im.getPos();
- im.initEntries(entries, chunks);
+ ManifestReader im = new ManifestReader(buf, mainAttributes);
+ mainEnd = im.getEndOfMainSection();
+ im.readEntries(entries, chunks);
}
/**
@@ -302,7 +300,7 @@
* If an error occurs writing the {@code Manifest}.
*/
static void write(Manifest manifest, OutputStream out) throws IOException {
- CharsetEncoder encoder = Charsets.UTF_8.newEncoder();
+ CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder();
ByteBuffer buffer = ByteBuffer.allocate(LINE_LENGTH_LIMIT);
Attributes.Name versionName = Attributes.Name.MANIFEST_VERSION;
@@ -325,7 +323,7 @@
Iterator<String> i = manifest.getEntries().keySet().iterator();
while (i.hasNext()) {
String key = i.next();
- writeEntry(out, NAME_ATTRIBUTE, key, encoder, buffer);
+ writeEntry(out, Attributes.Name.NAME, key, encoder, buffer);
Attributes attributes = manifest.entries.get(key);
Iterator<?> entries = attributes.keySet().iterator();
while (entries.hasNext()) {
@@ -339,7 +337,7 @@
private static void writeEntry(OutputStream os, Attributes.Name name,
String value, CharsetEncoder encoder, ByteBuffer bBuf) throws IOException {
String nameString = name.getName();
- os.write(nameString.getBytes(Charsets.US_ASCII));
+ os.write(nameString.getBytes(StandardCharsets.US_ASCII));
os.write(VALUE_SEPARATOR);
encoder.reset();
diff --git a/luni/src/main/java/java/util/jar/InitManifest.java b/luni/src/main/java/java/util/jar/ManifestReader.java
similarity index 81%
rename from luni/src/main/java/java/util/jar/InitManifest.java
rename to luni/src/main/java/java/util/jar/ManifestReader.java
index ade4790..2faaa90 100644
--- a/luni/src/main/java/java/util/jar/InitManifest.java
+++ b/luni/src/main/java/java/util/jar/ManifestReader.java
@@ -18,35 +18,42 @@
package java.util.jar;
import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
import java.util.Map;
/**
* Reads a JAR file manifest. The specification is here:
* http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html
*/
-class InitManifest {
+class ManifestReader {
+ // There are relatively few unique attribute names,
+ // 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 byte[] buf;
+ private final int endOfMainSection;
+
private int pos;
private Attributes.Name name;
private String value;
- private final UnsafeByteSequence valueBuffer = new UnsafeByteSequence(80);
private int consecutiveLineBreaks = 0;
- InitManifest(byte[] buf, Attributes main) throws IOException {
+ public ManifestReader(byte[] buf, Attributes main) throws IOException {
this.buf = buf;
while (readHeader()) {
main.put(name, value);
}
+ this.endOfMainSection = pos;
}
- void initEntries(Map<String, Attributes> entries,
- Map<String, Manifest.Chunk> chunks) throws IOException {
-
+ public void readEntries(Map<String, Attributes> entries, Map<String, Manifest.Chunk> chunks) throws IOException {
int mark = pos;
while (readHeader()) {
if (!Attributes.Name.NAME.equals(name)) {
@@ -81,8 +88,8 @@
}
}
- int getPos() {
- return pos;
+ public int getEndOfMainSection() {
+ return endOfMainSection;
}
/**
@@ -110,14 +117,18 @@
continue;
}
- String name = new String(buf, mark, pos - mark - 1, Charsets.US_ASCII);
+ String nameString = new String(buf, mark, pos - mark - 1, StandardCharsets.US_ASCII);
if (buf[pos++] != ' ') {
- throw new IOException(String.format("Invalid value for attribute '%s'", name));
+ throw new IOException(String.format("Invalid value for attribute '%s'", nameString));
}
try {
- this.name = new Attributes.Name(name);
+ name = attributeNameCache.get(nameString);
+ if (name == null) {
+ name = new Attributes.Name(nameString);
+ attributeNameCache.put(nameString, name);
+ }
} catch (IllegalArgumentException e) {
// new Attributes.Name() throws IllegalArgumentException but we declare IOException
throw new IOException(e.getMessage());
@@ -164,6 +175,6 @@
}
valueBuffer.write(buf, mark, last - mark);
- value = valueBuffer.toString(Charsets.UTF_8);
+ value = valueBuffer.toString(StandardCharsets.UTF_8);
}
}
diff --git a/luni/src/main/java/java/util/logging/Logger.java b/luni/src/main/java/java/util/logging/Logger.java
index 1c86dc8..3f2b787 100644
--- a/luni/src/main/java/java/util/logging/Logger.java
+++ b/luni/src/main/java/java/util/logging/Logger.java
@@ -91,8 +91,8 @@
/**
* The global logger is provided as convenience for casual use.
- * @deprecated deadlock-prone. Use {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)} as
- * a direct replacement, but see the discussion of how to use {@code Logger} in the class
+ * @deprecated This is deadlock-prone. Use {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)}
+ * as a direct replacement, but read the discussion of how to use {@link Logger} in the class
* documentation.
*/
@Deprecated
@@ -388,7 +388,6 @@
/**
* Returns the global {@code Logger}.
* @since 1.7
- * @hide 1.7
*/
public static Logger getGlobal() {
return global;
diff --git a/luni/src/main/java/java/util/prefs/AbstractPreferences.java b/luni/src/main/java/java/util/prefs/AbstractPreferences.java
index 71110c3..d2cb28e 100644
--- a/luni/src/main/java/java/util/prefs/AbstractPreferences.java
+++ b/luni/src/main/java/java/util/prefs/AbstractPreferences.java
@@ -19,7 +19,7 @@
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.EventListener;
import java.util.EventObject;
@@ -441,7 +441,7 @@
return EmptyArray.BYTE;
}
try {
- byte[] bavalue = svalue.getBytes(Charsets.US_ASCII);
+ byte[] bavalue = svalue.getBytes(StandardCharsets.US_ASCII);
if (bavalue.length % 4 != 0) {
return deflt;
}
diff --git a/luni/src/main/java/java/util/regex/Matcher.java b/luni/src/main/java/java/util/regex/Matcher.java
index 320e14c..d58d092 100644
--- a/luni/src/main/java/java/util/regex/Matcher.java
+++ b/luni/src/main/java/java/util/regex/Matcher.java
@@ -656,6 +656,16 @@
}
}
+ /**
+ * Returns a string representing this {@code Matcher}.
+ * The format of this string is unspecified.
+ */
+ @Override public String toString() {
+ return getClass().getName() + "[pattern=" + pattern() +
+ " region=" + regionStart() + "," + regionEnd() +
+ " lastmatch=" + (matchFound ? group() : "") + "]";
+ }
+
private static native void closeImpl(long addr);
private static native boolean findImpl(long addr, String s, int startIndex, int[] offsets);
private static native boolean findNextImpl(long addr, String s, int[] offsets);
diff --git a/luni/src/main/java/java/util/regex/Pattern.java b/luni/src/main/java/java/util/regex/Pattern.java
index 44b749e..a33ee93 100644
--- a/luni/src/main/java/java/util/regex/Pattern.java
+++ b/luni/src/main/java/java/util/regex/Pattern.java
@@ -104,8 +104,8 @@
* prefixed by {@code Is}. For example {@code \p{IsLu}} for all uppercase letters.
* <li>POSIX class names. These are 'Alnum', 'Alpha', 'ASCII', 'Blank', 'Cntrl', 'Digit',
* 'Graph', 'Lower', 'Print', 'Punct', 'Upper', 'XDigit'.
- * <li>Unicode block names, as used by {@link java.lang.Character.UnicodeBlock#forName} prefixed
- * by {@code In}. For example {@code \p{InHebrew}} for all characters in the Hebrew block.
+ * <li>Unicode block names, as accepted as input to {@link java.lang.Character.UnicodeBlock#forName},
+ * prefixed by {@code In}. For example {@code \p{InHebrew}} for all characters in the Hebrew block.
* <li>Character method names. These are all non-deprecated methods from {@link java.lang.Character}
* whose name starts with {@code is}, but with the {@code is} replaced by {@code java}.
* For example, {@code \p{javaLowerCase}}.
@@ -385,6 +385,10 @@
if ((flags & CANON_EQ) != 0) {
throw new UnsupportedOperationException("CANON_EQ flag not supported");
}
+ int supportedFlags = CASE_INSENSITIVE | COMMENTS | DOTALL | LITERAL | MULTILINE | UNICODE_CASE | UNIX_LINES;
+ if ((flags & ~supportedFlags) != 0) {
+ throw new IllegalArgumentException("Unsupported flags: " + (flags & ~supportedFlags));
+ }
this.pattern = pattern;
this.flags = flags;
compile();
diff --git a/luni/src/main/java/java/util/zip/CheckedInputStream.java b/luni/src/main/java/java/util/zip/CheckedInputStream.java
index 454098b..da6c635 100644
--- a/luni/src/main/java/java/util/zip/CheckedInputStream.java
+++ b/luni/src/main/java/java/util/zip/CheckedInputStream.java
@@ -68,35 +68,26 @@
}
/**
- * Reads up to n bytes of data from the underlying input stream, storing it
- * into {@code buf}, starting at offset {@code off}. The checksum is
+ * Reads up to {@code byteCount} bytes of data from the underlying input stream, storing it
+ * into {@code buffer}, starting at offset {@code byteOffset}. The checksum is
* updated with the bytes read.
+ * Returns the number of bytes actually read or {@code -1} if arrived at the
+ * end of the filtered stream while reading the data.
*
- * @param buf
- * the byte array in which to store the bytes read.
- * @param off
- * the initial position in {@code buf} to store the bytes read
- * from this stream.
- * @param nbytes
- * the maximum number of bytes to store in {@code buf}.
- * @return the number of bytes actually read or {@code -1} if arrived at the
- * end of the filtered stream while reading the data.
* @throws IOException
* if this stream is closed or some I/O error occurs.
*/
@Override
- public int read(byte[] buf, int off, int nbytes) throws IOException {
- int x = in.read(buf, off, nbytes);
- if (x != -1) {
- check.update(buf, off, x);
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ int bytesRead = in.read(buffer, byteOffset, byteCount);
+ if (bytesRead != -1) {
+ check.update(buffer, byteOffset, bytesRead);
}
- return x;
+ return bytesRead;
}
/**
* Returns the checksum calculated on the stream read so far.
- *
- * @return the updated checksum.
*/
public Checksum getChecksum() {
return check;
diff --git a/luni/src/main/java/java/util/zip/Deflater.java b/luni/src/main/java/java/util/zip/Deflater.java
index d96ab2a..3365031 100644
--- a/luni/src/main/java/java/util/zip/Deflater.java
+++ b/luni/src/main/java/java/util/zip/Deflater.java
@@ -106,8 +106,6 @@
/**
* Use buffering for best compression.
- *
- * @hide
* @since 1.7
*/
public static final int NO_FLUSH = 0;
@@ -115,8 +113,6 @@
/**
* Flush buffers so recipients can immediately decode the data sent thus
* far. This mode may degrade compression.
- *
- * @hide
* @since 1.7
*/
public static final int SYNC_FLUSH = 2;
@@ -126,8 +122,6 @@
* far. The compression state is also reset to permit random access and
* recovery for clients who have discarded or damaged their own copy. This
* mode may degrade compression.
- *
- * @hide
* @since 1.7
*/
public static final int FULL_FLUSH = 3;
@@ -228,7 +222,7 @@
* may have exceeded the output buffer's capacity. In this case,
* finishing a flush will require the output buffer to be drained
* and additional calls to {@link #deflate} to be made.
- * @hide
+ * @throws IllegalArgumentException if {@code flush} is invalid.
* @since 1.7
*/
public synchronized int deflate(byte[] buf, int offset, int byteCount, int flush) {
diff --git a/luni/src/main/java/java/util/zip/DeflaterInputStream.java b/luni/src/main/java/java/util/zip/DeflaterInputStream.java
index d854fec..f987e39a 100644
--- a/luni/src/main/java/java/util/zip/DeflaterInputStream.java
+++ b/luni/src/main/java/java/util/zip/DeflaterInputStream.java
@@ -106,14 +106,14 @@
}
/**
- * Reads compressed data into a byte buffer. The result will be bytes of compressed
+ * Reads up to {@code byteCount} bytes of compressed data into a byte buffer. The result will be bytes of compressed
* data corresponding to an uncompressed byte or bytes read from the underlying stream.
- * @return the number of bytes read or -1 if the end of the compressed input
- * stream has been reached.
+ * Returns the number of bytes read or -1 if the end of the compressed input
+ * stream has been reached.
*/
- @Override public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
checkClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
if (byteCount == 0) {
return 0;
}
@@ -137,7 +137,7 @@
if (bytesDeflated == -1) {
break;
}
- System.arraycopy(buf, 0, buffer, offset + count, bytesDeflated);
+ System.arraycopy(buf, 0, buffer, byteOffset + count, bytesDeflated);
count += bytesDeflated;
}
if (count == 0) {
diff --git a/luni/src/main/java/java/util/zip/DeflaterOutputStream.java b/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
index 448f61c..6cce5a5 100644
--- a/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
+++ b/luni/src/main/java/java/util/zip/DeflaterOutputStream.java
@@ -48,53 +48,28 @@
private final boolean syncFlush;
/**
- * This constructor lets you pass the {@code Deflater} specifying the
- * compression algorithm.
- *
- * @param os
- * is the {@code OutputStream} where to write the compressed data
- * to.
- * @param def
- * is the specific {@code Deflater} that is used to compress
- * data.
- */
- public DeflaterOutputStream(OutputStream os, Deflater def) {
- this(os, def, BUF_SIZE, false);
- }
-
- /**
- * This is the most basic constructor. You only need to pass the {@code
- * OutputStream} to which the compressed data shall be written to. The
- * default settings for the {@code Deflater} and internal buffer are used.
- * In particular the {@code Deflater} produces a ZLIB header in the output
- * stream.
- *
- * @param os
- * is the OutputStream where to write the compressed data to.
+ * Constructs a new instance with a default-constructed {@link Deflater}.
*/
public DeflaterOutputStream(OutputStream os) {
this(os, new Deflater(), BUF_SIZE, false);
}
/**
- * This constructor lets you specify both the compression algorithm as well
- * as the internal buffer size to be used.
- *
- * @param os
- * is the {@code OutputStream} where to write the compressed data
- * to.
- * @param def
- * is the specific {@code Deflater} that will be used to compress
- * data.
- * @param bufferSize
- * is the size to be used for the internal buffer.
+ * Constructs a new instance with the given {@code Deflater}.
+ */
+ public DeflaterOutputStream(OutputStream os, Deflater def) {
+ this(os, def, BUF_SIZE, false);
+ }
+
+ /**
+ * Constructs a new instance with the given {@code Deflater} and buffer size.
*/
public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize) {
this(os, def, bufferSize, false);
}
/**
- * @hide
+ * Constructs a new instance with the given flushing behavior (see {@link #flush}).
* @since 1.7
*/
public DeflaterOutputStream(OutputStream os, boolean syncFlush) {
@@ -102,7 +77,8 @@
}
/**
- * @hide
+ * Constructs a new instance with the given {@code Deflater} and
+ * flushing behavior (see {@link #flush}).
* @since 1.7
*/
public DeflaterOutputStream(OutputStream os, Deflater def, boolean syncFlush) {
@@ -110,7 +86,8 @@
}
/**
- * @hide
+ * Constructs a new instance with the given {@code Deflater}, buffer size, and
+ * flushing behavior (see {@link #flush}).
* @since 1.7
*/
public DeflaterOutputStream(OutputStream os, Deflater def, int bufferSize, boolean syncFlush) {
@@ -206,10 +183,9 @@
* Flushes the underlying stream. This flushes only the bytes that can be
* compressed at the highest level.
*
- * <p>For deflater output streams constructed with Java 7's
- * {@code syncFlush} parameter set to true (not yet available on Android),
- * this first flushes all outstanding data so that it may be immediately
- * read by its recipient. Doing so may degrade compression.
+ * <p>For deflater output streams constructed with the {@code syncFlush} parameter set to true,
+ * this first flushes all outstanding data so that it may be immediately read by its recipient.
+ * Doing so may degrade compression but improve interactive behavior.
*/
@Override public void flush() throws IOException {
if (syncFlush) {
diff --git a/luni/src/main/java/java/util/zip/GZIPInputStream.java b/luni/src/main/java/java/util/zip/GZIPInputStream.java
index fd73acc..08599ea 100644
--- a/luni/src/main/java/java/util/zip/GZIPInputStream.java
+++ b/luni/src/main/java/java/util/zip/GZIPInputStream.java
@@ -148,29 +148,25 @@
super.close();
}
- /**
- * Reads and decompresses GZIP data from the underlying stream into the
- * given buffer.
- */
@Override
- public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (closed) {
throw new IOException("Stream is closed");
}
if (eos) {
return -1;
}
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
int bytesRead;
try {
- bytesRead = super.read(buffer, offset, byteCount);
+ bytesRead = super.read(buffer, byteOffset, byteCount);
} finally {
eos = eof; // update eos after every read(), even when it throws
}
if (bytesRead != -1) {
- crc.update(buffer, offset, bytesRead);
+ crc.update(buffer, byteOffset, bytesRead);
}
if (eos) {
diff --git a/luni/src/main/java/java/util/zip/GZIPOutputStream.java b/luni/src/main/java/java/util/zip/GZIPOutputStream.java
index 7d30ae8..8dd907b 100644
--- a/luni/src/main/java/java/util/zip/GZIPOutputStream.java
+++ b/luni/src/main/java/java/util/zip/GZIPOutputStream.java
@@ -47,32 +47,39 @@
protected CRC32 crc = new CRC32();
/**
- * Construct a new {@code GZIPOutputStream} to write data in GZIP format to
- * the underlying stream.
- *
- * @param os
- * the {@code OutputStream} to write data to.
- * @throws IOException
- * if an {@code IOException} occurs.
+ * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+ * the given stream.
*/
public GZIPOutputStream(OutputStream os) throws IOException {
- this(os, BUF_SIZE);
+ this(os, BUF_SIZE, true);
}
/**
- * Construct a new {@code GZIPOutputStream} to write data in GZIP format to
- * the underlying stream. Set the internal compression buffer to size
- * {@code size}.
- *
- * @param os
- * the {@code OutputStream} to write to.
- * @param size
- * the internal buffer size.
- * @throws IOException
- * if an {@code IOException} occurs.
+ * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+ * the given stream with the given flushing behavior (see {@link DeflaterOutputStream#flush}).
+ * @since 1.7
*/
- public GZIPOutputStream(OutputStream os, int size) throws IOException {
- super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), size);
+ public GZIPOutputStream(OutputStream os, boolean syncFlush) throws IOException {
+ this(os, BUF_SIZE, syncFlush);
+ }
+
+ /**
+ * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+ * the given stream with the given internal buffer size and
+ * flushing behavior (see {@link DeflaterOutputStream#flush}).
+ */
+ public GZIPOutputStream(OutputStream os, int bufferSize) throws IOException {
+ this(os, bufferSize, true);
+ }
+
+ /**
+ * Constructs a new {@code GZIPOutputStream} to write data in GZIP format to
+ * the given stream with the given internal buffer size and
+ * flushing behavior (see {@link DeflaterOutputStream#flush}).
+ * @since 1.7
+ */
+ public GZIPOutputStream(OutputStream os, int bufferSize, boolean syncFlush) throws IOException {
+ super(os, new Deflater(Deflater.DEFAULT_COMPRESSION, true), bufferSize, syncFlush);
writeShort(GZIPInputStream.GZIP_MAGIC);
out.write(Deflater.DEFLATED);
out.write(0); // flags
diff --git a/luni/src/main/java/java/util/zip/InflaterInputStream.java b/luni/src/main/java/java/util/zip/InflaterInputStream.java
index 371c80a..25b2fe8 100644
--- a/luni/src/main/java/java/util/zip/InflaterInputStream.java
+++ b/luni/src/main/java/java/util/zip/InflaterInputStream.java
@@ -132,14 +132,13 @@
/**
* Reads up to {@code byteCount} bytes of decompressed data and stores it in
- * {@code buffer} starting at {@code offset}.
- *
- * @return Number of uncompressed bytes read
+ * {@code buffer} starting at {@code byteOffset}. Returns the number of uncompressed bytes read,
+ * or -1.
*/
@Override
- public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
checkClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
if (byteCount == 0) {
return 0;
@@ -156,7 +155,7 @@
// Invariant: if reading returns -1 or throws, eof must be true.
// It may also be true if the next read() should return -1.
try {
- int result = inf.inflate(buffer, offset, byteCount);
+ int result = inf.inflate(buffer, byteOffset, byteCount);
eof = inf.finished();
if (result > 0) {
return result;
diff --git a/luni/src/main/java/java/util/zip/ZipEntry.java b/luni/src/main/java/java/util/zip/ZipEntry.java
index e9168b5..e91c73e 100644
--- a/luni/src/main/java/java/util/zip/ZipEntry.java
+++ b/luni/src/main/java/java/util/zip/ZipEntry.java
@@ -20,7 +20,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteOrder;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -185,7 +185,7 @@
return;
}
- byte[] commentBytes = comment.getBytes(Charsets.UTF_8);
+ byte[] commentBytes = comment.getBytes(StandardCharsets.UTF_8);
if (commentBytes.length > 0xffff) {
throw new IllegalArgumentException("Comment too long: " + commentBytes.length);
}
@@ -387,14 +387,14 @@
if (containsNulByte(nameBytes)) {
throw new ZipException("Filename contains NUL byte: " + Arrays.toString(nameBytes));
}
- name = new String(nameBytes, 0, nameBytes.length, Charsets.UTF_8);
+ name = new String(nameBytes, 0, nameBytes.length, StandardCharsets.UTF_8);
// 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);
- comment = new String(commentBytes, 0, commentBytes.length, Charsets.UTF_8);
+ comment = new String(commentBytes, 0, commentBytes.length, StandardCharsets.UTF_8);
}
if (extraLength > 0) {
diff --git a/luni/src/main/java/java/util/zip/ZipFile.java b/luni/src/main/java/java/util/zip/ZipFile.java
index 519459b..47bc48e 100644
--- a/luni/src/main/java/java/util/zip/ZipFile.java
+++ b/luni/src/main/java/java/util/zip/ZipFile.java
@@ -19,6 +19,7 @@
import dalvik.system.CloseGuard;
import java.io.BufferedInputStream;
+import java.io.Closeable;
import java.io.EOFException;
import java.io.DataInputStream;
import java.io.File;
@@ -26,6 +27,7 @@
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -45,7 +47,7 @@
* <p>If you want to create a zip file, use {@link ZipOutputStream}. There is no API for updating
* an existing zip file.
*/
-public class ZipFile implements ZipConstants {
+public class ZipFile implements Closeable, ZipConstants {
/**
* General Purpose Bit Flags, Bit 0.
* If set, indicates that the file is encrypted.
@@ -101,6 +103,8 @@
private final LinkedHashMap<String, ZipEntry> entries = new LinkedHashMap<String, ZipEntry>();
+ private String comment;
+
private final CloseGuard guard = CloseGuard.get();
/**
@@ -220,6 +224,18 @@
}
/**
+ * Returns this file's comment, or null if it doesn't have one.
+ * See {@link ZipOutputStream#setComment}.
+ *
+ * @throws IllegalStateException if this zip file has been closed.
+ * @since 1.7
+ */
+ public String getComment() {
+ checkNotClosed();
+ return comment;
+ }
+
+ /**
* Returns the zip entry with the given name, or null if there is no such entry.
*
* @throws IllegalStateException if this zip file has been closed.
@@ -351,9 +367,9 @@
}
}
- // Read the End Of Central Directory. We could use ENDHDR instead of the magic number 18,
- // but we don't actually need all the header.
- byte[] eocd = new byte[18];
+ // Read the End Of Central Directory. ENDHDR includes the signature bytes,
+ // which we've already read.
+ byte[] eocd = new byte[ENDHDR - 4];
raf.readFully(eocd);
// Pull out the information we need.
@@ -364,11 +380,18 @@
int totalNumEntries = it.readShort() & 0xffff;
it.skip(4); // Ignore centralDirSize.
long centralDirOffset = ((long) it.readInt()) & 0xffffffffL;
+ int commentLength = it.readShort() & 0xffff;
if (numEntries != totalNumEntries || diskNumber != 0 || diskWithCentralDir != 0) {
throw new ZipException("spanned archives not supported");
}
+ if (commentLength > 0) {
+ byte[] commentBytes = new byte[commentLength];
+ raf.readFully(commentBytes);
+ comment = new String(commentBytes, 0, commentBytes.length, StandardCharsets.UTF_8);
+ }
+
// Seek to the first CDE and read all entries.
// We have to do this now (from the constructor) rather than lazily because the
// public API doesn't allow us to throw IOException except from the constructor
@@ -412,13 +435,13 @@
return Streams.readSingleByte(this);
}
- @Override public int read(byte[] b, int off, int len) throws IOException {
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
synchronized (sharedRaf) {
sharedRaf.seek(offset);
- if (len > length - offset) {
- len = (int) (length - offset);
+ if (byteCount > length - offset) {
+ byteCount = (int) (length - offset);
}
- int count = sharedRaf.read(b, off, len);
+ int count = sharedRaf.read(buffer, byteOffset, byteCount);
if (count > 0) {
offset += count;
return count;
@@ -457,8 +480,8 @@
this.entry = entry;
}
- @Override public int read(byte[] buffer, int off, int nbytes) throws IOException {
- int i = super.read(buffer, off, nbytes);
+ @Override public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
+ int i = super.read(buffer, byteOffset, byteCount);
if (i != -1) {
bytesRead += i;
}
diff --git a/luni/src/main/java/java/util/zip/ZipInputStream.java b/luni/src/main/java/java/util/zip/ZipInputStream.java
index d46e2dd..9c18f49 100644
--- a/luni/src/main/java/java/util/zip/ZipInputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipInputStream.java
@@ -286,15 +286,13 @@
}
/**
- * Reads up to the specified number of uncompressed bytes into the buffer
- * starting at the offset.
- *
- * @return the number of bytes read
+ * Reads up to {@code byteCount} uncompressed bytes into the buffer
+ * starting at {@code byteOffset}. Returns the number of bytes actually read, or -1.
*/
@Override
- public int read(byte[] buffer, int offset, int byteCount) throws IOException {
+ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
checkClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, byteCount);
+ Arrays.checkOffsetAndCount(buffer.length, byteOffset, byteCount);
if (inf.finished() || currentEntry == null) {
return -1;
@@ -317,10 +315,10 @@
if ((csize - inRead) < toRead) {
toRead = csize - inRead;
}
- System.arraycopy(buf, lastRead, buffer, offset, toRead);
+ System.arraycopy(buf, lastRead, buffer, byteOffset, toRead);
lastRead += toRead;
inRead += toRead;
- crc.update(buffer, offset, toRead);
+ crc.update(buffer, byteOffset, toRead);
return toRead;
}
if (inf.needsInput()) {
@@ -331,14 +329,14 @@
}
int read;
try {
- read = inf.inflate(buffer, offset, byteCount);
+ read = inf.inflate(buffer, byteOffset, byteCount);
} catch (DataFormatException e) {
throw new ZipException(e.getMessage());
}
if (read == 0 && inf.finished()) {
return -1;
}
- crc.update(buffer, offset, read);
+ crc.update(buffer, byteOffset, read);
return read;
}
diff --git a/luni/src/main/java/java/util/zip/ZipOutputStream.java b/luni/src/main/java/java/util/zip/ZipOutputStream.java
index 59849d3..04de03f 100644
--- a/luni/src/main/java/java/util/zip/ZipOutputStream.java
+++ b/luni/src/main/java/java/util/zip/ZipOutputStream.java
@@ -20,7 +20,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashSet;
import libcore.util.EmptyArray;
@@ -69,7 +69,7 @@
*/
public static final int STORED = 0;
- private static final int ZIPLocalHeaderVersionNeeded = 20;
+ private static final int ZIP_VERSION_2_0 = 20; // Zip specification version 2.0.
private byte[] commentBytes = EmptyArray.BYTE;
@@ -158,8 +158,8 @@
// http://code.google.com/p/android/issues/detail?id=20214
flags |= ZipFile.GPBF_UTF8_FLAG;
writeLong(cDir, CENSIG);
- writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version created
- writeShort(cDir, ZIPLocalHeaderVersionNeeded); // Version to extract
+ writeShort(cDir, ZIP_VERSION_2_0); // Version this file was made by.
+ writeShort(cDir, ZIP_VERSION_2_0); // Minimum version needed to extract.
writeShort(cDir, flags);
writeShort(cDir, currentEntry.getMethod());
writeShort(cDir, currentEntry.time);
@@ -182,7 +182,7 @@
String comment = currentEntry.getComment();
byte[] commentBytes = EmptyArray.BYTE;
if (comment != null) {
- commentBytes = comment.getBytes(Charsets.UTF_8);
+ commentBytes = comment.getBytes(StandardCharsets.UTF_8);
}
writeShort(cDir, commentBytes.length); // Comment length.
writeShort(cDir, 0); // Disk Start
@@ -294,7 +294,7 @@
// TODO: support Zip64.
throw new ZipException("Too many entries for the zip file format's 16-bit entry count");
}
- nameBytes = ze.name.getBytes(Charsets.UTF_8);
+ nameBytes = ze.name.getBytes(StandardCharsets.UTF_8);
nameLength = nameBytes.length;
if (nameLength > 0xffff) {
throw new IllegalArgumentException("Name too long: " + nameLength + " UTF-8 bytes");
@@ -313,7 +313,7 @@
// modified UTF-8. From Java 7, it sets this flag and uses normal UTF-8.)
flags |= ZipFile.GPBF_UTF8_FLAG;
writeLong(out, LOCSIG); // Entry header
- writeShort(out, ZIPLocalHeaderVersionNeeded); // Extraction version
+ writeShort(out, ZIP_VERSION_2_0); // Minimum version needed to extract.
writeShort(out, flags);
writeShort(out, method);
if (currentEntry.getTime() == -1) {
@@ -344,7 +344,7 @@
}
/**
- * Sets the comment associated with the file being written.
+ * Sets the comment associated with the file being written. See {@link ZipFile#getComment}.
* @throws IllegalArgumentException if the comment is >= 64 Ki UTF-8 bytes.
*/
public void setComment(String comment) {
@@ -353,7 +353,7 @@
return;
}
- byte[] newCommentBytes = comment.getBytes(Charsets.UTF_8);
+ byte[] newCommentBytes = comment.getBytes(StandardCharsets.UTF_8);
if (newCommentBytes.length > 0xffff) {
throw new IllegalArgumentException("Comment too long: " + newCommentBytes.length + " bytes");
}
diff --git a/luni/src/main/java/javax/crypto/AEADBadTagException.java b/luni/src/main/java/javax/crypto/AEADBadTagException.java
new file mode 100644
index 0000000..d5d1b11
--- /dev/null
+++ b/luni/src/main/java/javax/crypto/AEADBadTagException.java
@@ -0,0 +1,43 @@
+/*
+ * 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 javax.crypto;
+
+/**
+ * Thrown by a {@link Cipher} that is using an Authenticated Encryption with
+ * Additional Data (AEAD) mode such as Galois/Counter Mode (GCM) and the tag
+ * failed verification.
+ *
+ * @since 1.7
+ */
+public class AEADBadTagException extends BadPaddingException {
+ private static final long serialVersionUID = -488059093241685509L;
+
+ /**
+ * Constructs an instance of {@code AEADBadTagException}.
+ */
+ public AEADBadTagException() {
+ super();
+ }
+
+ /**
+ * Constructs an instance of {@code AEADBadTagException} with the given
+ * {@code message}.
+ */
+ public AEADBadTagException(String message) {
+ super(message);
+ }
+}
diff --git a/luni/src/main/java/javax/crypto/Cipher.java b/luni/src/main/java/javax/crypto/Cipher.java
index aeb5def..ba40b86 100644
--- a/luni/src/main/java/javax/crypto/Cipher.java
+++ b/luni/src/main/java/javax/crypto/Cipher.java
@@ -875,7 +875,7 @@
* if this cipher instance is not initialized for encryption or
* decryption.
* @throws IllegalArgumentException
- * if the input is {@code null}, or if {@code inputOffset} and
+ * if {@code input} is {@code null}, or if {@code inputOffset} and
* {@code inputLen} do not specify a valid chunk in the input
* buffer.
*/
@@ -1026,6 +1026,99 @@
}
/**
+ * Continues a multi-part transformation (encryption or decryption) with
+ * Authenticated Additional Data (AAD). AAD may only be added after the
+ * {@code Cipher} is initialized and before any data is passed to the
+ * instance.
+ * <p>
+ * This is only usable with cipher modes that support Authenticated
+ * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+ *
+ * @param input bytes of AAD to use with the cipher
+ * @throws IllegalStateException
+ * if this cipher instance is not initialized for encryption or
+ * decryption.
+ * @throws IllegalArgumentException
+ * if {@code input} is {@code null}
+ * @throws UnsupportedOperationException if the cipher does not support AEAD
+ * @since 1.7
+ */
+ public final void updateAAD(byte[] input) {
+ if (input == null) {
+ throw new IllegalArgumentException("input == null");
+ }
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+ throw new IllegalStateException();
+ }
+ if (input.length == 0) {
+ return;
+ }
+ spiImpl.engineUpdateAAD(input, 0, input.length);
+ }
+
+ /**
+ * Continues a multi-part transformation (encryption or decryption) with
+ * Authenticated Additional Data (AAD). AAD may only be added after the
+ * {@code Cipher} is initialized and before any data is passed to the
+ * instance.
+ * <p>
+ * This is only usable with cipher modes that support Authenticated
+ * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+ *
+ * @param input bytes of AAD to use with the cipher
+ * @param inputOffset offset within bytes of additional data to add to cipher
+ * @param inputLen length of bytes of additional data to add to cipher
+ * @throws IllegalStateException
+ * if this cipher instance is not initialized for encryption or
+ * decryption.
+ * @throws IllegalArgumentException
+ * if {@code input} is {@code null}, or if {@code inputOffset} and
+ * {@code inputLen} do not specify a valid chunk in the input
+ * buffer.
+ * @throws UnsupportedOperationException if the cipher does not support AEAD
+ * @since 1.7
+ */
+ public final void updateAAD(byte[] input, int inputOffset, int inputLen) {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+ throw new IllegalStateException();
+ }
+ if (input == null) {
+ throw new IllegalArgumentException("input == null");
+ }
+ checkInputOffsetAndCount(input.length, inputOffset, inputLen);
+ if (input.length == 0) {
+ return;
+ }
+ spiImpl.engineUpdateAAD(input, inputOffset, inputLen);
+ }
+
+ /**
+ * Continues a multi-part transformation (encryption or decryption) with
+ * Authenticated Additional Data (AAD). AAD may only be added after the
+ * {@code Cipher} is initialized and before any data is passed to the
+ * instance.
+ * <p>
+ * This is only usable with cipher modes that support Authenticated
+ * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+ *
+ * @param input buffer of AAD to be used
+ * @throws IllegalStateException
+ * if this cipher instance is not initialized for encryption or
+ * decryption.
+ * @throws UnsupportedOperationException if the cipher does not support AEAD
+ * @since 1.7
+ */
+ public final void updateAAD(ByteBuffer input) {
+ if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
+ throw new IllegalStateException("Cipher is not initialized");
+ }
+ if (input == null) {
+ throw new IllegalArgumentException("input == null");
+ }
+ spiImpl.engineUpdateAAD(input);
+ }
+
+ /**
* Finishes a multi-part transformation (encryption or decryption).
* <p>
* Processes any bytes that may have been buffered in previous {@code
diff --git a/luni/src/main/java/javax/crypto/CipherSpi.java b/luni/src/main/java/javax/crypto/CipherSpi.java
index 1f91ba8..70e06b1 100644
--- a/luni/src/main/java/javax/crypto/CipherSpi.java
+++ b/luni/src/main/java/javax/crypto/CipherSpi.java
@@ -368,6 +368,69 @@
}
/**
+ * Continues a multi-part transformation (encryption or decryption) with
+ * Authenticated Additional Data (AAD). AAD may only be added after the
+ * {@code Cipher} is initialized and before any data is passed to the
+ * instance.
+ * <p>
+ * This is only usable with cipher modes that support Authenticated
+ * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+ *
+ * @param input bytes of AAD to use with the cipher
+ * @param inputOffset offset within bytes of additional data to add to cipher
+ * @param inputLen length of bytes of additional data to add to cipher
+ * @throws IllegalStateException
+ * if this cipher instance is not initialized for encryption or
+ * decryption.
+ * @throws IllegalArgumentException
+ * if {@code input} is {@code null}, or if {@code inputOffset} and
+ * {@code inputLen} do not specify a valid chunk in the input
+ * buffer.
+ * @throws UnsupportedOperationException if the cipher does not support AEAD
+ * @since 1.7
+ */
+ protected void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+ throw new UnsupportedOperationException(
+ "This cipher does not support Authenticated Encryption with Additional Data");
+ }
+
+ /**
+ * Continues a multi-part transformation (encryption or decryption). The
+ * {@code input.remaining()} bytes starting at {@code input.position()} are
+ * used for the Additional Authenticated Data (AAD). AAD may only be added
+ * after the {@code Cipher} is initialized and before any data is passed to
+ * the instance.
+ * <p>
+ * This is only usable with cipher modes that support Authenticated
+ * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
+ *
+ * @param input the input buffer to transform.
+ * @since 1.7
+ */
+ protected void engineUpdateAAD(ByteBuffer input) {
+ if (input == null) {
+ throw new NullPointerException("input == null");
+ }
+ int position = input.position();
+ int limit = input.limit();
+ if ((limit - position) <= 0) {
+ return;
+ }
+ byte[] bInput;
+ if (input.hasArray()) {
+ bInput = input.array();
+ int offset = input.arrayOffset();
+ engineUpdateAAD(bInput, offset + position, limit - position);
+ input.position(limit);
+ } else {
+ int len = limit - position;
+ bInput = new byte[len];
+ input.get(bInput);
+ engineUpdateAAD(bInput, 0, len);
+ }
+ }
+
+ /**
* Finishes a multi-part transformation (encryption or decryption).
* <p>
* Processes the {@code inputLen} bytes in {@code input} buffer at {@code
diff --git a/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java b/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
new file mode 100644
index 0000000..a781697
--- /dev/null
+++ b/luni/src/main/java/javax/crypto/spec/GCMParameterSpec.java
@@ -0,0 +1,97 @@
+/*
+ * 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 javax.crypto.spec;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.util.Arrays;
+
+/**
+ * Provides a the parameters for an instance of a {@link javax.crypto.Cipher}
+ * using Galois/Counter Mode (GCM). This is an Authenticated Encryption with
+ * Associated Data (AEAD) mode for a cipher which allows you to use the
+ * {@link javax.crypto.Cipher#updateAAD(byte[])} method to provide data that is
+ * transmitted in the clear but authenticated using a cryptographic Message
+ * Authentication Code (MAC).
+ *
+ * @since 1.7
+ */
+public class GCMParameterSpec implements AlgorithmParameterSpec {
+ private final int tagLen;
+
+ private final byte[] iv;
+
+ /**
+ * Creates a new {@code GCMParameterSpec} instance from the specified
+ * Initial Vector (IV) from buffer {@code iv} and a tag length of
+ * {@code tagLen} in bits.
+ *
+ * @throws IllegalArgumentException if the specified {@code iv} is null or
+ * {@code offset} and {@code byteCount} do not specify a valid
+ * chunk in the specified buffer.
+ */
+ public GCMParameterSpec(int tagLen, byte[] iv) {
+ if (tagLen < 0) {
+ throw new IllegalArgumentException("tag should be a non-negative integer");
+ }
+ if (iv == null) {
+ throw new IllegalArgumentException("iv == null");
+ }
+ this.tagLen = tagLen;
+ this.iv = iv.clone();
+ }
+
+ /**
+ * Creates a new {@code GCMParameterSpec} instance with the Initial Vector
+ * (IV) of {@code byteCount} bytes from the specified buffer {@code iv}
+ * starting at {@code offset} and a tag length of {@code tagLen} in bits.
+ *
+ * @throws IllegalArgumentException if the specified {@code iv} is null or
+ * {@code offset} and {@code byteCount} do not specify a valid
+ * chunk in the specified buffer.
+ * @throws ArrayIndexOutOfBoundsException if {@code offset} or
+ * {@code byteCount} are negative.
+ */
+ public GCMParameterSpec(int tagLen, byte[] iv, int offset, int byteCount) {
+ if (tagLen < 0) {
+ throw new IllegalArgumentException("tag should be a non-negative integer");
+ }
+ if (iv == null) {
+ throw new IllegalArgumentException("iv == null");
+ }
+ try {
+ Arrays.checkOffsetAndCount(iv.length, offset, byteCount);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new IllegalArgumentException(e);
+ }
+ this.tagLen = tagLen;
+ this.iv = Arrays.copyOfRange(iv, offset, offset + byteCount);
+ }
+
+ /**
+ * Returns the size of the tag in bits.
+ */
+ public int getTLen() {
+ return tagLen;
+ }
+
+ /**
+ * Returns the Initial Vector (IV) used by this parameter spec.
+ */
+ public byte[] getIV() {
+ return iv.clone();
+ }
+}
diff --git a/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java b/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
index 05caa0b..5779d17 100644
--- a/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
+++ b/luni/src/main/java/libcore/icu/CollationElementIteratorICU.java
@@ -155,12 +155,12 @@
return order & TERTIARY_ORDER_MASK_;
}
- public static CollationElementIteratorICU getInstance(int collatorAddress, String source) {
- int iteratorAddress = NativeCollation.getCollationElementIterator(collatorAddress, source);
+ public static CollationElementIteratorICU getInstance(long collatorAddress, String source) {
+ long iteratorAddress = NativeCollation.getCollationElementIterator(collatorAddress, source);
return new CollationElementIteratorICU(iteratorAddress);
}
- private CollationElementIteratorICU(int address) {
+ private CollationElementIteratorICU(long address) {
this.address = address;
}
@@ -184,7 +184,7 @@
/**
* C collator
*/
- private int address;
+ private final long address;
/**
* ICU constant primary order mask for collation elements
diff --git a/luni/src/main/java/libcore/icu/DateIntervalFormat.java b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
new file mode 100644
index 0000000..a3e1e5e
--- /dev/null
+++ b/luni/src/main/java/libcore/icu/DateIntervalFormat.java
@@ -0,0 +1,150 @@
+/*
+ * 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.icu;
+
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Exposes icu4c's DateIntervalFormat.
+ */
+public final class DateIntervalFormat {
+
+ // 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;
+ 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;
+
+ // TODO: check whether icu4c's DateIntervalFormat is expensive enough to warrant a native peer.
+ private DateIntervalFormat() {
+ }
+
+ // This is public DateUtils API in frameworks/base.
+ public static String formatDateRange(long startMs, long endMs, int flags, String olsonId) {
+ if ((flags & FORMAT_UTC) != 0) {
+ olsonId = "UTC";
+ }
+ TimeZone tz = (olsonId != null) ? TimeZone.getTimeZone(olsonId) : TimeZone.getDefault();
+ return formatDateRange(Locale.getDefault(), tz, startMs, endMs, flags);
+ }
+
+ // 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);
+
+ Calendar endCalendar;
+ if (startMs == endMs) {
+ endCalendar = startCalendar;
+ } else {
+ endCalendar = Calendar.getInstance(tz);
+ endCalendar.setTimeInMillis(endMs);
+ }
+
+ if ((flags & FORMAT_ABBREV_ALL) != 0) {
+ flags |= FORMAT_ABBREV_MONTH | FORMAT_ABBREV_TIME | FORMAT_ABBREV_WEEKDAY;
+ }
+
+ String monthPart = "MMMM";
+ if ((flags & FORMAT_NUMERIC_DATE) != 0) {
+ monthPart = "M";
+ } else if ((flags & FORMAT_ABBREV_MONTH) != 0) {
+ monthPart = "MMM";
+ }
+
+ String weekPart = "EEEE";
+ if ((flags & FORMAT_ABBREV_WEEKDAY) != 0) {
+ weekPart = "EEE";
+ }
+
+ String timePart = "j"; // "j" means choose 12 or 24 hour based on current locale.
+ if ((flags & FORMAT_24HOUR) != 0) {
+ timePart = "H";
+ } else if ((flags & FORMAT_12HOUR) != 0) {
+ timePart = "h";
+ }
+ if ((flags & FORMAT_ABBREV_TIME) == 0 || !onTheHour(startCalendar) || !onTheHour(endCalendar)) {
+ timePart = timePart + "m";
+ }
+
+ if (fallOnDifferentDates(startCalendar, endCalendar)) {
+ flags |= FORMAT_SHOW_DATE;
+ }
+
+ if (fallInSameMonth(startCalendar, endCalendar) && (flags & FORMAT_NO_MONTH_DAY) != 0) {
+ flags &= (~FORMAT_SHOW_WEEKDAY);
+ flags &= (~FORMAT_SHOW_TIME);
+ }
+
+ if ((flags & (FORMAT_SHOW_DATE | FORMAT_SHOW_TIME | FORMAT_SHOW_WEEKDAY)) == 0) {
+ flags |= FORMAT_SHOW_DATE;
+ }
+
+ StringBuilder builder = new StringBuilder();
+ if ((flags & (FORMAT_SHOW_DATE | FORMAT_NO_MONTH_DAY)) != 0) {
+ if ((flags & FORMAT_SHOW_YEAR) != 0) {
+ builder.append("y");
+ }
+ builder.append(monthPart);
+ if ((flags & FORMAT_NO_MONTH_DAY) == 0) {
+ builder.append("d");
+ }
+ }
+ if ((flags & FORMAT_SHOW_WEEKDAY) != 0) {
+ builder.append(weekPart);
+ }
+ if ((flags & FORMAT_SHOW_TIME) != 0) {
+ builder.append(timePart);
+ }
+ return builder.toString();
+ }
+
+ private static boolean onTheHour(Calendar c) {
+ return c.get(Calendar.MINUTE) == 0 && c.get(Calendar.SECOND) == 0;
+ }
+
+ private static boolean fallOnDifferentDates(Calendar c1, Calendar c2) {
+ return c1.get(Calendar.YEAR) != c2.get(Calendar.YEAR) ||
+ c1.get(Calendar.MONTH) != c2.get(Calendar.MONTH) ||
+ c1.get(Calendar.DAY_OF_MONTH) != c2.get(Calendar.DAY_OF_MONTH);
+ }
+
+ private static boolean fallInSameMonth(Calendar c1, Calendar c2) {
+ return c1.get(Calendar.MONTH) == c2.get(Calendar.MONTH);
+ }
+
+ private static native String formatDateInterval(String skeleton, String localeName, String timeZoneName, 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 8e0cd0b..6a72d44 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -129,6 +129,47 @@
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.
+ }
+ }
+ return result;
+ }
+
/**
* Returns the version of the CLDR data in use, such as "22.1.1".
*/
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index 7a8607b..a6d700f 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -79,6 +79,10 @@
public String mediumDateFormat;
public String shortDateFormat;
+ // shortDateFormat, but guaranteed to have 4-digit years.
+ // Used by android.text.format.DateFormat.getDateFormatStringForSetting.
+ public String shortDateFormat4;
+
// Used by android.text.format.DateFormat.getTimeFormat.
public String timeFormat12; // "hh:mm a"
public String timeFormat24; // "HH:mm"
@@ -187,6 +191,7 @@
// accidentally eat too much.
localeData.integerPattern = localeData.numberPattern.replaceAll("\\.[#,]*", "");
}
+ localeData.shortDateFormat4 = localeData.shortDateFormat.replaceAll("\\byy\\b", "y");
return localeData;
}
}
diff --git a/luni/src/main/java/libcore/icu/NativeBreakIterator.java b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
index 4156f9a..7168d96 100644
--- a/luni/src/main/java/libcore/icu/NativeBreakIterator.java
+++ b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
@@ -29,13 +29,13 @@
// The address of the native peer.
// Uses of this must be manually synchronized to avoid native crashes.
- private final int address;
+ private final long address;
private final int type;
private String string;
private CharacterIterator charIterator;
- private NativeBreakIterator(int address, int type) {
+ private NativeBreakIterator(long address, int type) {
this.address = address;
this.type = type;
this.charIterator = new StringCharacterIterator("");
@@ -43,7 +43,7 @@
@Override
public Object clone() {
- int cloneAddr = cloneImpl(this.address);
+ long cloneAddr = cloneImpl(this.address);
NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
clone.string = this.string;
// The RI doesn't clone the CharacterIterator.
@@ -157,21 +157,21 @@
return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
}
- private static native int getCharacterInstanceImpl(String locale);
- private static native int getWordInstanceImpl(String locale);
- private static native int getLineInstanceImpl(String locale);
- private static native int getSentenceInstanceImpl(String locale);
- private static synchronized native int cloneImpl(int address);
+ private static native long getCharacterInstanceImpl(String locale);
+ private static native long getWordInstanceImpl(String locale);
+ private static native long getLineInstanceImpl(String locale);
+ private static native long getSentenceInstanceImpl(String locale);
+ private static synchronized native long cloneImpl(long address);
- private static synchronized native void closeImpl(int address);
+ private static synchronized native void closeImpl(long address);
- private static synchronized native void setTextImpl(int address, String text);
- private static synchronized native int precedingImpl(int address, String text, int offset);
- private static synchronized native boolean isBoundaryImpl(int address, String text, int offset);
- private static synchronized native int nextImpl(int address, String text, int n);
- private static synchronized native int previousImpl(int address, String text);
- private static synchronized native int currentImpl(int address, String text);
- private static synchronized native int firstImpl(int address, String text);
- private static synchronized native int followingImpl(int address, String text, int offset);
- private static synchronized native int lastImpl(int address, String text);
+ private static synchronized native void setTextImpl(long address, String text);
+ private static synchronized native int precedingImpl(long address, String text, int offset);
+ private static synchronized native boolean isBoundaryImpl(long address, String text, int offset);
+ private static synchronized native int nextImpl(long address, String text, int n);
+ private static synchronized native int previousImpl(long address, String text);
+ private static synchronized native int currentImpl(long address, String text);
+ private static synchronized native int firstImpl(long address, String text);
+ private static synchronized native int followingImpl(long address, String text, int offset);
+ private static synchronized native int lastImpl(long address, String text);
}
diff --git a/luni/src/main/java/libcore/icu/NativeCollation.java b/luni/src/main/java/libcore/icu/NativeCollation.java
index 2f61c49..0373fef 100644
--- a/luni/src/main/java/libcore/icu/NativeCollation.java
+++ b/luni/src/main/java/libcore/icu/NativeCollation.java
@@ -20,24 +20,24 @@
}
// Collator.
- public static native void closeCollator(int address);
- public static native int compare(int address, String source, String target);
- public static native int getAttribute(int address, int type);
- public static native int getCollationElementIterator(int address, String source);
- public static native String getRules(int address);
- public static native byte[] getSortKey(int address, String source);
- public static native int openCollator(String locale);
- public static native int openCollatorFromRules(String rules, int normalizationMode, int collationStrength);
- public static native int safeClone(int address);
- public static native void setAttribute(int address, int type, int value);
+ public static native void closeCollator(long address);
+ public static native int compare(long address, String source, String target);
+ public static native int getAttribute(long address, int type);
+ public static native int getCollationElementIterator(long address, String source);
+ public static native String getRules(long address);
+ public static native byte[] getSortKey(long address, String source);
+ public static native long openCollator(String locale);
+ public static native long openCollatorFromRules(String rules, int normalizationMode, int collationStrength);
+ public static native long safeClone(long address);
+ public static native void setAttribute(long address, int type, int value);
// CollationElementIterator.
- public static native void closeElements(int address);
- public static native int getMaxExpansion(int address, int order);
- public static native int getOffset(int address);
- public static native int next(int address);
- public static native int previous(int address);
- public static native void reset(int address);
- public static native void setOffset(int address, int offset);
- public static native void setText(int address, String source);
+ public static native void closeElements(long address);
+ public static native int getMaxExpansion(long address, int order);
+ public static native int getOffset(long address);
+ public static native int next(long address);
+ public static native int previous(long address);
+ public static native void reset(long address);
+ public static native void setOffset(long address, int offset);
+ public static native void setText(long address, String source);
}
diff --git a/luni/src/main/java/libcore/icu/NativeConverter.java b/luni/src/main/java/libcore/icu/NativeConverter.java
index 1b8a7e0..17be458 100644
--- a/luni/src/main/java/libcore/icu/NativeConverter.java
+++ b/luni/src/main/java/libcore/icu/NativeConverter.java
@@ -36,8 +36,6 @@
public static native boolean contains(String converterName1, String converterName2);
- public static native boolean canEncode(long converterHandle, int codeUnit);
-
public static native String[] getAvailableCharsetNames();
public static native Charset charsetForName(String charsetName);
diff --git a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
index 376526e..0e9ffc4 100644
--- a/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
+++ b/luni/src/main/java/libcore/icu/NativeDecimalFormat.java
@@ -621,7 +621,7 @@
}
private static native void applyPatternImpl(long addr, boolean localized, String pattern);
- private static native int cloneImpl(long addr);
+ private static native long cloneImpl(long addr);
private static native void close(long addr);
private static native char[] formatLong(long addr, long value, FieldPositionIterator iter);
private static native char[] formatDouble(long addr, double value, FieldPositionIterator iter);
diff --git a/luni/src/main/java/libcore/icu/NativePluralRules.java b/luni/src/main/java/libcore/icu/NativePluralRules.java
index 47cc76b..dbcf089 100644
--- a/luni/src/main/java/libcore/icu/NativePluralRules.java
+++ b/luni/src/main/java/libcore/icu/NativePluralRules.java
@@ -32,9 +32,9 @@
public static final int MANY = 4;
public static final int OTHER = 5;
- private final int address;
+ private final long address;
- private NativePluralRules(int address) {
+ private NativePluralRules(long address) {
this.address = address;
}
@@ -58,7 +58,7 @@
return quantityForIntImpl(address, value);
}
- private static native void finalizeImpl(int address);
- private static native int forLocaleImpl(String localeName);
- private static native int quantityForIntImpl(int address, int value);
+ private static native void finalizeImpl(long address);
+ private static native long forLocaleImpl(String localeName);
+ private static native int quantityForIntImpl(long address, int value);
}
diff --git a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
index 4221fe6..3ea942d 100644
--- a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
+++ b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
@@ -42,7 +42,7 @@
public static final int STRENGTH = 5;
// The address of the ICU4C native peer.
- private int address;
+ private final long address;
public RuleBasedCollatorICU(String rules) throws ParseException {
if (rules == null) {
@@ -55,7 +55,7 @@
address = NativeCollation.openCollator(locale.toString());
}
- private RuleBasedCollatorICU(int address) {
+ private RuleBasedCollatorICU(long address) {
this.address = address;
}
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index 2db0381..5bb54a1 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -149,7 +149,7 @@
public static String[] forLocale(Locale locale) {
String countryCode = locale.getCountry();
ArrayList<String> ids = new ArrayList<String>();
- for (String line : ZoneInfoDB.getZoneTab().split("\n")) {
+ for (String line : ZoneInfoDB.getInstance().getZoneTab().split("\n")) {
if (line.startsWith(countryCode)) {
int olsonIdStart = line.indexOf('\t', 4) + 1;
int olsonIdEnd = line.indexOf('\t', olsonIdStart);
diff --git a/luni/src/main/java/libcore/io/Base64.java b/luni/src/main/java/libcore/io/Base64.java
index e4643b5..00b0251 100644
--- a/luni/src/main/java/libcore/io/Base64.java
+++ b/luni/src/main/java/libcore/io/Base64.java
@@ -21,7 +21,7 @@
package libcore.io;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import libcore.util.EmptyArray;
/**
@@ -156,6 +156,6 @@
out[index++] = '=';
break;
}
- return new String(out, 0, index, Charsets.US_ASCII);
+ return new String(out, 0, index, StandardCharsets.US_ASCII);
}
}
diff --git a/luni/src/main/java/libcore/io/DiskLruCache.java b/luni/src/main/java/libcore/io/DiskLruCache.java
deleted file mode 100644
index b9cc0a1..0000000
--- a/luni/src/main/java/libcore/io/DiskLruCache.java
+++ /dev/null
@@ -1,860 +0,0 @@
-/*
- * 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 libcore.io;
-
-import java.io.BufferedWriter;
-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.FileWriter;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.nio.charset.Charsets;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A cache that uses a bounded amount of space on a filesystem. Each cache
- * entry has a string key and a fixed number of values. Values are byte
- * sequences, accessible as streams or files. Each value must be between {@code
- * 0} and {@code Integer.MAX_VALUE} bytes in length.
- *
- * <p>The cache stores its data in a directory on the filesystem. This
- * directory must be exclusive to the cache; the cache may delete or overwrite
- * files from its directory. It is an error for multiple processes to use the
- * same cache directory at the same time.
- *
- * <p>This cache limits the number of bytes that it will store on the
- * filesystem. When the number of stored bytes exceeds the limit, the cache will
- * remove entries in the background until the limit is satisfied. The limit is
- * not strict: the cache may temporarily exceed it while waiting for files to be
- * deleted. The limit does not include filesystem overhead or the cache
- * journal so space-sensitive applications should set a conservative limit.
- *
- * <p>Clients call {@link #edit} to create or update the values of an entry. An
- * entry may have only one editor at one time; if a value is not available to be
- * edited then {@link #edit} will return null.
- * <ul>
- * <li>When an entry is being <strong>created</strong> it is necessary to
- * supply a full set of values; the empty value should be used as a
- * placeholder if necessary.
- * <li>When an entry is being <strong>edited</strong>, it is not necessary
- * to supply data for every value; values default to their previous
- * value.
- * </ul>
- * Every {@link #edit} call must be matched by a call to {@link Editor#commit}
- * or {@link Editor#abort}. Committing is atomic: a read observes the full set
- * of values as they were before or after the commit, but never a mix of values.
- *
- * <p>Clients call {@link #get} to read a snapshot of an entry. The read will
- * observe the value at the time that {@link #get} was called. Updates and
- * removals after the call do not impact ongoing reads.
- *
- * <p>This class is tolerant of some I/O errors. If files are missing from the
- * filesystem, the corresponding entries will be dropped from the cache. If
- * an error occurs while writing a cache value, the edit will fail silently.
- * Callers should handle other problems by catching {@code IOException} and
- * responding appropriately.
- */
-public final class DiskLruCache implements Closeable {
- static final String JOURNAL_FILE = "journal";
- static final String JOURNAL_FILE_TMP = "journal.tmp";
- static final String MAGIC = "libcore.io.DiskLruCache";
- static final String VERSION_1 = "1";
- static final long ANY_SEQUENCE_NUMBER = -1;
- private static final String CLEAN = "CLEAN";
- private static final String DIRTY = "DIRTY";
- private static final String REMOVE = "REMOVE";
- private static final String READ = "READ";
-
- /*
- * This cache uses a journal file named "journal". A typical journal file
- * looks like this:
- * libcore.io.DiskLruCache
- * 1
- * 100
- * 2
- *
- * CLEAN 3400330d1dfc7f3f7f4b8d4d803dfcf6 832 21054
- * DIRTY 335c4c6028171cfddfbaae1a9c313c52
- * CLEAN 335c4c6028171cfddfbaae1a9c313c52 3934 2342
- * REMOVE 335c4c6028171cfddfbaae1a9c313c52
- * DIRTY 1ab96a171faeeee38496d8b330771a7a
- * CLEAN 1ab96a171faeeee38496d8b330771a7a 1600 234
- * READ 335c4c6028171cfddfbaae1a9c313c52
- * READ 3400330d1dfc7f3f7f4b8d4d803dfcf6
- *
- * The first five lines of the journal form its header. They are the
- * constant string "libcore.io.DiskLruCache", the disk cache's version,
- * the application's version, the value count, and a blank line.
- *
- * Each of the subsequent lines in the file is a record of the state of a
- * cache entry. Each line contains space-separated values: a state, a key,
- * and optional state-specific values.
- * o DIRTY lines track that an entry is actively being created or updated.
- * Every successful DIRTY action should be followed by a CLEAN or REMOVE
- * action. DIRTY lines without a matching CLEAN or REMOVE indicate that
- * temporary files may need to be deleted.
- * o CLEAN lines track a cache entry that has been successfully published
- * and may be read. A publish line is followed by the lengths of each of
- * its values.
- * o READ lines track accesses for LRU.
- * o REMOVE lines track entries that have been deleted.
- *
- * The journal file is appended to as cache operations occur. The journal may
- * occasionally be compacted by dropping redundant lines. A temporary file named
- * "journal.tmp" will be used during compaction; that file should be deleted if
- * it exists when the cache is opened.
- */
-
- private final File directory;
- private final File journalFile;
- private final File journalFileTmp;
- private final int appVersion;
- private final long maxSize;
- private final int valueCount;
- private long size = 0;
- private Writer journalWriter;
- private final LinkedHashMap<String, Entry> lruEntries
- = new LinkedHashMap<String, Entry>(0, 0.75f, true);
- private int redundantOpCount;
-
- /**
- * To differentiate between old and current snapshots, each entry is given
- * a sequence number each time an edit is committed. A snapshot is stale if
- * its sequence number is not equal to its entry's sequence number.
- */
- private long nextSequenceNumber = 0;
-
- /** This cache uses a single background thread to evict entries. */
- private final ExecutorService executorService = new ThreadPoolExecutor(0, 1,
- 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
- private final Callable<Void> cleanupCallable = new Callable<Void>() {
- @Override public Void call() throws Exception {
- synchronized (DiskLruCache.this) {
- if (journalWriter == null) {
- return null; // closed
- }
- trimToSize();
- if (journalRebuildRequired()) {
- rebuildJournal();
- redundantOpCount = 0;
- }
- }
- return null;
- }
- };
-
- private DiskLruCache(File directory, int appVersion, int valueCount, long maxSize) {
- this.directory = directory;
- this.appVersion = appVersion;
- this.journalFile = new File(directory, JOURNAL_FILE);
- this.journalFileTmp = new File(directory, JOURNAL_FILE_TMP);
- this.valueCount = valueCount;
- this.maxSize = maxSize;
- }
-
- /**
- * Opens the cache in {@code directory}, creating a cache if none exists
- * there.
- *
- * @param directory a writable directory
- * @param appVersion
- * @param valueCount the number of values per cache entry. Must be positive.
- * @param maxSize the maximum number of bytes this cache should use to store
- * @throws IOException if reading or writing the cache directory fails
- */
- public static DiskLruCache open(File directory, int appVersion, int valueCount, long maxSize)
- throws IOException {
- if (maxSize <= 0) {
- throw new IllegalArgumentException("maxSize <= 0");
- }
- if (valueCount <= 0) {
- throw new IllegalArgumentException("valueCount <= 0");
- }
-
- // prefer to pick up where we left off
- DiskLruCache cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
- if (cache.journalFile.exists()) {
- try {
- cache.readJournal();
- cache.processJournal();
- cache.journalWriter = new BufferedWriter(new FileWriter(cache.journalFile, true));
- return cache;
- } catch (IOException journalIsCorrupt) {
- System.logW("DiskLruCache " + directory + " is corrupt: "
- + journalIsCorrupt.getMessage() + ", removing");
- cache.delete();
- }
- }
-
- // create a new empty cache
- directory.mkdirs();
- cache = new DiskLruCache(directory, appVersion, valueCount, maxSize);
- cache.rebuildJournal();
- return cache;
- }
-
- private void readJournal() throws IOException {
- StrictLineReader reader = new StrictLineReader(new FileInputStream(journalFile),
- Charsets.US_ASCII);
- try {
- String magic = reader.readLine();
- String version = reader.readLine();
- String appVersionString = reader.readLine();
- String valueCountString = reader.readLine();
- String blank = reader.readLine();
- if (!MAGIC.equals(magic)
- || !VERSION_1.equals(version)
- || !Integer.toString(appVersion).equals(appVersionString)
- || !Integer.toString(valueCount).equals(valueCountString)
- || !"".equals(blank)) {
- throw new IOException("unexpected journal header: ["
- + magic + ", " + version + ", " + valueCountString + ", " + blank + "]");
- }
-
- int lineCount = 0;
- while (true) {
- try {
- readJournalLine(reader.readLine());
- lineCount++;
- } catch (EOFException endOfJournal) {
- break;
- }
- }
- redundantOpCount = lineCount - lruEntries.size();
- } finally {
- IoUtils.closeQuietly(reader);
- }
- }
-
- private void readJournalLine(String line) throws IOException {
- int firstSpace = line.indexOf(' ');
- if (firstSpace == -1) {
- throw new IOException("unexpected journal line: " + line);
- }
-
- int keyBegin = firstSpace + 1;
- int secondSpace = line.indexOf(' ', keyBegin);
- final String key;
- if (secondSpace == -1) {
- key = line.substring(keyBegin);
- if (firstSpace == REMOVE.length() && line.startsWith(REMOVE)) {
- lruEntries.remove(key);
- return;
- }
- } else {
- key = line.substring(keyBegin, secondSpace);
- }
-
- Entry entry = lruEntries.get(key);
- if (entry == null) {
- entry = new Entry(key);
- lruEntries.put(key, entry);
- }
-
- if (secondSpace != -1 && firstSpace == CLEAN.length() && line.startsWith(CLEAN)) {
- String[] parts = line.substring(secondSpace + 1).split(" ");
- entry.readable = true;
- entry.currentEditor = null;
- entry.setLengths(parts);
- } else if (secondSpace == -1 && firstSpace == DIRTY.length() && line.startsWith(DIRTY)) {
- entry.currentEditor = new Editor(entry);
- } else if (secondSpace == -1 && firstSpace == READ.length() && line.startsWith(READ)) {
- // this work was already done by calling lruEntries.get()
- } else {
- throw new IOException("unexpected journal line: " + line);
- }
- }
-
- /**
- * Computes the initial size and collects garbage as a part of opening the
- * cache. Dirty entries are assumed to be inconsistent and will be deleted.
- */
- private void processJournal() throws IOException {
- deleteIfExists(journalFileTmp);
- for (Iterator<Entry> i = lruEntries.values().iterator(); i.hasNext(); ) {
- Entry entry = i.next();
- if (entry.currentEditor == null) {
- for (int t = 0; t < valueCount; t++) {
- size += entry.lengths[t];
- }
- } else {
- entry.currentEditor = null;
- for (int t = 0; t < valueCount; t++) {
- deleteIfExists(entry.getCleanFile(t));
- deleteIfExists(entry.getDirtyFile(t));
- }
- i.remove();
- }
- }
- }
-
- /**
- * Creates a new journal that omits redundant information. This replaces the
- * current journal if it exists.
- */
- private synchronized void rebuildJournal() throws IOException {
- if (journalWriter != null) {
- journalWriter.close();
- }
-
- Writer writer = new BufferedWriter(new FileWriter(journalFileTmp));
- writer.write(MAGIC);
- writer.write("\n");
- writer.write(VERSION_1);
- writer.write("\n");
- writer.write(Integer.toString(appVersion));
- writer.write("\n");
- writer.write(Integer.toString(valueCount));
- writer.write("\n");
- writer.write("\n");
-
- for (Entry entry : lruEntries.values()) {
- if (entry.currentEditor != null) {
- writer.write(DIRTY + ' ' + entry.key + '\n');
- } else {
- writer.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
- }
- }
-
- writer.close();
- journalFileTmp.renameTo(journalFile);
- journalWriter = new BufferedWriter(new FileWriter(journalFile, true));
- }
-
- private static void deleteIfExists(File file) throws IOException {
- try {
- Libcore.os.remove(file.getPath());
- } catch (ErrnoException errnoException) {
- if (errnoException.errno != OsConstants.ENOENT) {
- throw errnoException.rethrowAsIOException();
- }
- }
- }
-
- /**
- * Returns a snapshot of the entry named {@code key}, or null if it doesn't
- * exist is not currently readable. If a value is returned, it is moved to
- * the head of the LRU queue.
- */
- public synchronized Snapshot get(String key) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (entry == null) {
- return null;
- }
-
- if (!entry.readable) {
- return null;
- }
-
- /*
- * Open all streams eagerly to guarantee that we see a single published
- * snapshot. If we opened streams lazily then the streams could come
- * from different edits.
- */
- InputStream[] ins = new InputStream[valueCount];
- try {
- for (int i = 0; i < valueCount; i++) {
- ins[i] = new FileInputStream(entry.getCleanFile(i));
- }
- } catch (FileNotFoundException e) {
- // a file must have been deleted manually!
- return null;
- }
-
- redundantOpCount++;
- journalWriter.append(READ + ' ' + key + '\n');
- if (journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
-
- return new Snapshot(key, entry.sequenceNumber, ins);
- }
-
- /**
- * Returns an editor for the entry named {@code key}, or null if another
- * edit is in progress.
- */
- public Editor edit(String key) throws IOException {
- return edit(key, ANY_SEQUENCE_NUMBER);
- }
-
- private synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (expectedSequenceNumber != ANY_SEQUENCE_NUMBER
- && (entry == null || entry.sequenceNumber != expectedSequenceNumber)) {
- return null; // snapshot is stale
- }
- if (entry == null) {
- entry = new Entry(key);
- lruEntries.put(key, entry);
- } else if (entry.currentEditor != null) {
- return null; // another edit is in progress
- }
-
- Editor editor = new Editor(entry);
- entry.currentEditor = editor;
-
- // flush the journal before creating files to prevent file leaks
- journalWriter.write(DIRTY + ' ' + key + '\n');
- journalWriter.flush();
- return editor;
- }
-
- /**
- * Returns the directory where this cache stores its data.
- */
- public File getDirectory() {
- return directory;
- }
-
- /**
- * Returns the maximum number of bytes that this cache should use to store
- * its data.
- */
- public long maxSize() {
- return maxSize;
- }
-
- /**
- * Returns the number of bytes currently being used to store the values in
- * this cache. This may be greater than the max size if a background
- * deletion is pending.
- */
- public synchronized long size() {
- return size;
- }
-
- private synchronized void completeEdit(Editor editor, boolean success) throws IOException {
- Entry entry = editor.entry;
- if (entry.currentEditor != editor) {
- throw new IllegalStateException();
- }
-
- // if this edit is creating the entry for the first time, every index must have a value
- if (success && !entry.readable) {
- for (int i = 0; i < valueCount; i++) {
- if (!editor.written[i]) {
- editor.abort();
- throw new IllegalStateException("Newly created entry didn't create value for index " + i);
- }
- if (!entry.getDirtyFile(i).exists()) {
- editor.abort();
- System.logW("DiskLruCache: Newly created entry doesn't have file for index " + i);
- return;
- }
- }
- }
-
- for (int i = 0; i < valueCount; i++) {
- File dirty = entry.getDirtyFile(i);
- if (success) {
- if (dirty.exists()) {
- File clean = entry.getCleanFile(i);
- dirty.renameTo(clean);
- long oldLength = entry.lengths[i];
- long newLength = clean.length();
- entry.lengths[i] = newLength;
- size = size - oldLength + newLength;
- }
- } else {
- deleteIfExists(dirty);
- }
- }
-
- redundantOpCount++;
- entry.currentEditor = null;
- if (entry.readable | success) {
- entry.readable = true;
- journalWriter.write(CLEAN + ' ' + entry.key + entry.getLengths() + '\n');
- if (success) {
- entry.sequenceNumber = nextSequenceNumber++;
- }
- } else {
- lruEntries.remove(entry.key);
- journalWriter.write(REMOVE + ' ' + entry.key + '\n');
- }
-
- if (size > maxSize || journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
- }
-
- /**
- * We only rebuild the journal when it will halve the size of the journal
- * and eliminate at least 2000 ops.
- */
- private boolean journalRebuildRequired() {
- final int REDUNDANT_OP_COMPACT_THRESHOLD = 2000;
- return redundantOpCount >= REDUNDANT_OP_COMPACT_THRESHOLD
- && redundantOpCount >= lruEntries.size();
- }
-
- /**
- * Drops the entry for {@code key} if it exists and can be removed. Entries
- * actively being edited cannot be removed.
- *
- * @return true if an entry was removed.
- */
- public synchronized boolean remove(String key) throws IOException {
- checkNotClosed();
- validateKey(key);
- Entry entry = lruEntries.get(key);
- if (entry == null || entry.currentEditor != null) {
- return false;
- }
-
- for (int i = 0; i < valueCount; i++) {
- File file = entry.getCleanFile(i);
- if (!file.delete()) {
- throw new IOException("failed to delete " + file);
- }
- size -= entry.lengths[i];
- entry.lengths[i] = 0;
- }
-
- redundantOpCount++;
- journalWriter.append(REMOVE + ' ' + key + '\n');
- lruEntries.remove(key);
-
- if (journalRebuildRequired()) {
- executorService.submit(cleanupCallable);
- }
-
- return true;
- }
-
- /**
- * Returns true if this cache has been closed.
- */
- public boolean isClosed() {
- return journalWriter == null;
- }
-
- private void checkNotClosed() {
- if (journalWriter == null) {
- throw new IllegalStateException("cache is closed");
- }
- }
-
- /**
- * Force buffered operations to the filesystem.
- */
- public synchronized void flush() throws IOException {
- checkNotClosed();
- trimToSize();
- journalWriter.flush();
- }
-
- /**
- * Closes this cache. Stored values will remain on the filesystem.
- */
- public synchronized void close() throws IOException {
- if (journalWriter == null) {
- return; // already closed
- }
- for (Entry entry : new ArrayList<Entry>(lruEntries.values())) {
- if (entry.currentEditor != null) {
- entry.currentEditor.abort();
- }
- }
- trimToSize();
- journalWriter.close();
- journalWriter = null;
- }
-
- private void trimToSize() throws IOException {
- while (size > maxSize) {
- Map.Entry<String, Entry> toEvict = lruEntries.eldest();
- remove(toEvict.getKey());
- }
- }
-
- /**
- * Closes the cache and deletes all of its stored values. This will delete
- * all files in the cache directory including files that weren't created by
- * the cache.
- */
- public void delete() throws IOException {
- close();
- IoUtils.deleteContents(directory);
- }
-
- private void validateKey(String key) {
- if (key.contains(" ") || key.contains("\n") || key.contains("\r")) {
- throw new IllegalArgumentException(
- "keys must not contain spaces or newlines: \"" + key + "\"");
- }
- }
-
- private static String inputStreamToString(InputStream in) throws IOException {
- return Streams.readFully(new InputStreamReader(in, Charsets.UTF_8));
- }
-
- /**
- * A snapshot of the values for an entry.
- */
- public final class Snapshot implements Closeable {
- private final String key;
- private final long sequenceNumber;
- private final InputStream[] ins;
-
- private Snapshot(String key, long sequenceNumber, InputStream[] ins) {
- this.key = key;
- this.sequenceNumber = sequenceNumber;
- this.ins = ins;
- }
-
- /**
- * Returns an editor for this snapshot's entry, or null if either the
- * entry has changed since this snapshot was created or if another edit
- * is in progress.
- */
- public Editor edit() throws IOException {
- return DiskLruCache.this.edit(key, sequenceNumber);
- }
-
- /**
- * Returns the unbuffered stream with the value for {@code index}.
- */
- public InputStream getInputStream(int index) {
- return ins[index];
- }
-
- /**
- * Returns the string value for {@code index}.
- */
- public String getString(int index) throws IOException {
- return inputStreamToString(getInputStream(index));
- }
-
- @Override public void close() {
- for (InputStream in : ins) {
- IoUtils.closeQuietly(in);
- }
- }
- }
-
- /**
- * Edits the values for an entry.
- */
- public final class Editor {
- private final Entry entry;
- private final boolean[] written;
- private boolean hasErrors;
-
- private Editor(Entry entry) {
- this.entry = entry;
- this.written = (entry.readable) ? null : new boolean[valueCount];
- }
-
- /**
- * Returns an unbuffered input stream to read the last committed value,
- * or null if no value has been committed.
- */
- public InputStream newInputStream(int index) throws IOException {
- synchronized (DiskLruCache.this) {
- if (entry.currentEditor != this) {
- throw new IllegalStateException();
- }
- if (!entry.readable) {
- return null;
- }
- return new FileInputStream(entry.getCleanFile(index));
- }
- }
-
- /**
- * Returns the last committed value as a string, or null if no value
- * has been committed.
- */
- public String getString(int index) throws IOException {
- InputStream in = newInputStream(index);
- return in != null ? inputStreamToString(in) : null;
- }
-
- /**
- * Returns a new unbuffered output stream to write the value at
- * {@code index}. If the underlying output stream encounters errors
- * when writing to the filesystem, this edit will be aborted when
- * {@link #commit} is called. The returned output stream does not throw
- * IOExceptions.
- */
- public OutputStream newOutputStream(int index) throws IOException {
- synchronized (DiskLruCache.this) {
- if (entry.currentEditor != this) {
- throw new IllegalStateException();
- }
- if (!entry.readable) {
- written[index] = true;
- }
- return new FaultHidingOutputStream(new FileOutputStream(entry.getDirtyFile(index)));
- }
- }
-
- /**
- * Sets the value at {@code index} to {@code value}.
- */
- public void set(int index, String value) throws IOException {
- Writer writer = null;
- try {
- writer = new OutputStreamWriter(newOutputStream(index), Charsets.UTF_8);
- writer.write(value);
- } finally {
- IoUtils.closeQuietly(writer);
- }
- }
-
- /**
- * Commits this edit so it is visible to readers. This releases the
- * edit lock so another edit may be started on the same key.
- */
- public void commit() throws IOException {
- if (hasErrors) {
- completeEdit(this, false);
- remove(entry.key); // the previous entry is stale
- } else {
- completeEdit(this, true);
- }
- }
-
- /**
- * Aborts this edit. This releases the edit lock so another edit may be
- * started on the same key.
- */
- public void abort() throws IOException {
- completeEdit(this, false);
- }
-
- private class FaultHidingOutputStream extends FilterOutputStream {
- private FaultHidingOutputStream(OutputStream out) {
- super(out);
- }
-
- @Override public void write(int oneByte) {
- try {
- out.write(oneByte);
- } catch (IOException e) {
- hasErrors = true;
- }
- }
-
- @Override public void write(byte[] buffer, int offset, int length) {
- try {
- out.write(buffer, offset, length);
- } catch (IOException e) {
- hasErrors = true;
- }
- }
-
- @Override public void close() {
- try {
- out.close();
- } catch (IOException e) {
- hasErrors = true;
- }
- }
-
- @Override public void flush() {
- try {
- out.flush();
- } catch (IOException e) {
- hasErrors = true;
- }
- }
- }
- }
-
- private final class Entry {
- private final String key;
-
- /** Lengths of this entry's files. */
- private final long[] lengths;
-
- /** True if this entry has ever been published */
- private boolean readable;
-
- /** The ongoing edit or null if this entry is not being edited. */
- private Editor currentEditor;
-
- /** The sequence number of the most recently committed edit to this entry. */
- private long sequenceNumber;
-
- private Entry(String key) {
- this.key = key;
- this.lengths = new long[valueCount];
- }
-
- public String getLengths() throws IOException {
- StringBuilder result = new StringBuilder();
- for (long size : lengths) {
- result.append(' ').append(size);
- }
- return result.toString();
- }
-
- /**
- * Set lengths using decimal numbers like "10123".
- */
- private void setLengths(String[] strings) throws IOException {
- if (strings.length != valueCount) {
- throw invalidLengths(strings);
- }
-
- try {
- for (int i = 0; i < strings.length; i++) {
- lengths[i] = Long.parseLong(strings[i]);
- }
- } catch (NumberFormatException e) {
- throw invalidLengths(strings);
- }
- }
-
- private IOException invalidLengths(String[] strings) throws IOException {
- throw new IOException("unexpected journal line: " + Arrays.toString(strings));
- }
-
- public File getCleanFile(int i) {
- return new File(directory, key + "." + i);
- }
-
- public File getDirtyFile(int i) {
- return new File(directory, key + "." + i + ".tmp");
- }
- }
-}
diff --git a/luni/src/main/java/libcore/io/ForwardingOs.java b/luni/src/main/java/libcore/io/ForwardingOs.java
index 2de13ae..3800416 100644
--- a/luni/src/main/java/libcore/io/ForwardingOs.java
+++ b/luni/src/main/java/libcore/io/ForwardingOs.java
@@ -54,7 +54,7 @@
public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException { return os.fcntlFlock(fd, cmd, arg); }
public void fdatasync(FileDescriptor fd) throws ErrnoException { os.fdatasync(fd); }
public StructStat fstat(FileDescriptor fd) throws ErrnoException { return os.fstat(fd); }
- public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException { return os.fstatfs(fd); }
+ public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException { return os.fstatvfs(fd); }
public void fsync(FileDescriptor fd) throws ErrnoException { os.fsync(fd); }
public void ftruncate(FileDescriptor fd, long length) throws ErrnoException { os.ftruncate(fd, length); }
public String gai_strerror(int error) { return os.gai_strerror(error); }
@@ -76,6 +76,7 @@
public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptLinger(fd, level, option); }
public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptTimeval(fd, level, option); }
public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException { return os.getsockoptUcred(fd, level, option); }
+ public int gettid() { return os.gettid(); }
public int getuid() { return os.getuid(); }
public String if_indextoname(int index) { return os.if_indextoname(index); }
public InetAddress inet_pton(int family, String address) { return os.inet_pton(family, address); }
@@ -128,7 +129,7 @@
public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException { return os.socket(domain, type, protocol); }
public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException { os.socketpair(domain, type, protocol, fd1, fd2); }
public StructStat stat(String path) throws ErrnoException { return os.stat(path); }
- public StructStatFs statfs(String path) throws ErrnoException { return os.statfs(path); }
+ public StructStatVfs statvfs(String path) throws ErrnoException { return os.statvfs(path); }
public String strerror(int errno) { return os.strerror(errno); }
public String strsignal(int signal) { return os.strsignal(signal); }
public void symlink(String oldPath, String newPath) throws ErrnoException { os.symlink(oldPath, newPath); }
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index 089d0f8..28adba1 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -577,23 +577,23 @@
}
}
- public static InetAddress getSocketLocalAddress(FileDescriptor fd) {
+ public static InetAddress getSocketLocalAddress(FileDescriptor fd) throws SocketException {
try {
SocketAddress sa = Libcore.os.getsockname(fd);
InetSocketAddress isa = (InetSocketAddress) sa;
return isa.getAddress();
} catch (ErrnoException errnoException) {
- throw new AssertionError(errnoException);
+ throw errnoException.rethrowAsSocketException();
}
}
- public static int getSocketLocalPort(FileDescriptor fd) {
+ public static int getSocketLocalPort(FileDescriptor fd) throws SocketException {
try {
SocketAddress sa = Libcore.os.getsockname(fd);
InetSocketAddress isa = (InetSocketAddress) sa;
return isa.getPort();
} catch (ErrnoException errnoException) {
- throw new AssertionError(errnoException);
+ throw errnoException.rethrowAsSocketException();
}
}
}
diff --git a/luni/src/main/java/libcore/io/IoUtils.java b/luni/src/main/java/libcore/io/IoUtils.java
index 24ffd58..f7cc41f 100644
--- a/luni/src/main/java/libcore/io/IoUtils.java
+++ b/luni/src/main/java/libcore/io/IoUtils.java
@@ -22,10 +22,13 @@
import java.io.InterruptedIOException;
import java.io.RandomAccessFile;
import java.net.Socket;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
import static libcore.io.OsConstants.*;
public final class IoUtils {
+ private static final Random TEMPORARY_DIRECTORY_PRNG = new Random();
+
private IoUtils() {
}
@@ -107,7 +110,7 @@
* 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(Charsets.UTF_8);
+ return readFileAsBytes(path).toString(StandardCharsets.UTF_8);
}
private static UnsafeByteSequence readFileAsBytes(String path) throws IOException {
@@ -129,28 +132,47 @@
}
/**
- * Recursively delete everything in {@code dir}.
+ * Do not use. Use createTemporaryDirectory instead.
+ *
+ * Used by frameworks/base unit tests to clean up a temporary directory.
+ * Deliberately ignores errors, on the assumption that test cleanup is only
+ * supposed to be best-effort.
+ *
+ * @deprecated Use {@link #createTemporaryDirectory} instead.
*/
- // TODO: this should specify paths as Strings rather than as Files
public static void deleteContents(File dir) throws IOException {
File[] files = dir.listFiles();
- if (files == null) {
- throw new IOException("listFiles returned null: " + dir);
- }
- for (File file : files) {
- if (file.isDirectory()) {
- deleteContents(file);
- }
- if (!file.delete()) {
- throw new IOException("failed to delete file: " + file);
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ deleteContents(file);
+ }
+ file.delete();
}
}
}
/**
+ * Creates a unique new temporary directory under "java.io.tmpdir".
+ */
+ public static File createTemporaryDirectory(String prefix) {
+ while (true) {
+ String candidateName = prefix + TEMPORARY_DIRECTORY_PRNG.nextInt();
+ File result = new File(System.getProperty("java.io.tmpdir"), candidateName);
+ if (result.mkdir()) {
+ return result;
+ }
+ }
+ }
+
+ /**
+ * Do not use. This is for System.loadLibrary use only.
+ *
* Checks whether {@code path} can be opened read-only. Similar to File.exists, but doesn't
* require read permission on the parent, so it'll work in more cases, and allow you to
- * remove read permission from more directories.
+ * remove read permission from more directories. Everyone else should just open(2) and then
+ * use the fd, but the loadLibrary API is broken by its need to ask ClassLoaders where to
+ * find a .so rather than just calling dlopen(3).
*/
public static boolean canOpenReadOnly(String path) {
try {
diff --git a/luni/src/main/java/libcore/io/Os.java b/luni/src/main/java/libcore/io/Os.java
index f3d2383..2b68027 100644
--- a/luni/src/main/java/libcore/io/Os.java
+++ b/luni/src/main/java/libcore/io/Os.java
@@ -45,7 +45,7 @@
public int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
public void fdatasync(FileDescriptor fd) throws ErrnoException;
public StructStat fstat(FileDescriptor fd) throws ErrnoException;
- public StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException;
+ public StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
public void fsync(FileDescriptor fd) throws ErrnoException;
public void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
public String gai_strerror(int error);
@@ -68,6 +68,7 @@
public StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
public StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
public StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public int gettid();
public int getuid();
public String if_indextoname(int index);
public InetAddress inet_pton(int family, String address);
@@ -121,8 +122,7 @@
public FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
public void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
public StructStat stat(String path) throws ErrnoException;
- /* TODO: replace statfs with statvfs. */
- public StructStatFs statfs(String path) throws ErrnoException;
+ public StructStatVfs statvfs(String path) throws ErrnoException;
public String strerror(int errno);
public String strsignal(int signal);
public void symlink(String oldPath, String newPath) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/OsConstants.java b/luni/src/main/java/libcore/io/OsConstants.java
index bb5c766..edecdd9 100644
--- a/luni/src/main/java/libcore/io/OsConstants.java
+++ b/luni/src/main/java/libcore/io/OsConstants.java
@@ -46,6 +46,43 @@
public static final int AI_NUMERICSERV = placeholder();
public static final int AI_PASSIVE = placeholder();
public static final int AI_V4MAPPED = placeholder();
+ public static final int CAP_AUDIT_CONTROL = placeholder();
+ public static final int CAP_AUDIT_WRITE = placeholder();
+ public static final int CAP_CHOWN = placeholder();
+ public static final int CAP_DAC_OVERRIDE = placeholder();
+ public static final int CAP_DAC_READ_SEARCH = placeholder();
+ public static final int CAP_FOWNER = placeholder();
+ public static final int CAP_FSETID = placeholder();
+ public static final int CAP_IPC_LOCK = placeholder();
+ public static final int CAP_IPC_OWNER = placeholder();
+ public static final int CAP_KILL = placeholder();
+ public static final int CAP_LAST_CAP = placeholder();
+ public static final int CAP_LEASE = placeholder();
+ public static final int CAP_LINUX_IMMUTABLE = placeholder();
+ public static final int CAP_MAC_ADMIN = placeholder();
+ public static final int CAP_MAC_OVERRIDE = placeholder();
+ public static final int CAP_MKNOD = placeholder();
+ public static final int CAP_NET_ADMIN = placeholder();
+ public static final int CAP_NET_BIND_SERVICE = placeholder();
+ public static final int CAP_NET_BROADCAST = placeholder();
+ public static final int CAP_NET_RAW = placeholder();
+ public static final int CAP_SETFCAP = placeholder();
+ public static final int CAP_SETGID = placeholder();
+ public static final int CAP_SETPCAP = placeholder();
+ public static final int CAP_SETUID = placeholder();
+ public static final int CAP_SYS_ADMIN = placeholder();
+ public static final int CAP_SYS_BOOT = placeholder();
+ public static final int CAP_SYS_CHROOT = placeholder();
+ public static final int CAP_SYSLOG = placeholder();
+ public static final int CAP_SYS_MODULE = placeholder();
+ public static final int CAP_SYS_NICE = placeholder();
+ public static final int CAP_SYS_PACCT = placeholder();
+ public static final int CAP_SYS_PTRACE = placeholder();
+ public static final int CAP_SYS_RAWIO = placeholder();
+ public static final int CAP_SYS_RESOURCE = placeholder();
+ public static final int CAP_SYS_TIME = placeholder();
+ public static final int CAP_SYS_TTY_CONFIG = placeholder();
+ public static final int CAP_WAKE_ALARM = placeholder();
public static final int E2BIG = placeholder();
public static final int EACCES = placeholder();
public static final int EADDRINUSE = placeholder();
@@ -174,6 +211,7 @@
public static final int IFF_SLAVE = placeholder();
public static final int IFF_UP = placeholder();
public static final int IPPROTO_ICMP = placeholder();
+ public static final int IPPROTO_ICMPV6 = placeholder();
public static final int IPPROTO_IP = placeholder();
public static final int IPPROTO_IPV6 = placeholder();
public static final int IPPROTO_RAW = placeholder();
diff --git a/luni/src/main/java/libcore/io/Posix.java b/luni/src/main/java/libcore/io/Posix.java
index e9d1da3..b99941c 100644
--- a/luni/src/main/java/libcore/io/Posix.java
+++ b/luni/src/main/java/libcore/io/Posix.java
@@ -48,7 +48,7 @@
public native int fcntlFlock(FileDescriptor fd, int cmd, StructFlock arg) throws ErrnoException;
public native void fdatasync(FileDescriptor fd) throws ErrnoException;
public native StructStat fstat(FileDescriptor fd) throws ErrnoException;
- public native StructStatFs fstatfs(FileDescriptor fd) throws ErrnoException;
+ public native StructStatVfs fstatvfs(FileDescriptor fd) throws ErrnoException;
public native void fsync(FileDescriptor fd) throws ErrnoException;
public native void ftruncate(FileDescriptor fd, long length) throws ErrnoException;
public native String gai_strerror(int error);
@@ -70,6 +70,7 @@
public native StructLinger getsockoptLinger(FileDescriptor fd, int level, int option) throws ErrnoException;
public native StructTimeval getsockoptTimeval(FileDescriptor fd, int level, int option) throws ErrnoException;
public native StructUcred getsockoptUcred(FileDescriptor fd, int level, int option) throws ErrnoException;
+ public native int gettid();
public native int getuid();
public native String if_indextoname(int index);
public native InetAddress inet_pton(int family, String address);
@@ -172,7 +173,7 @@
public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
public native void socketpair(int domain, int type, int protocol, FileDescriptor fd1, FileDescriptor fd2) throws ErrnoException;
public native StructStat stat(String path) throws ErrnoException;
- public native StructStatFs statfs(String path) throws ErrnoException;
+ public native StructStatVfs statvfs(String path) throws ErrnoException;
public native String strerror(int errno);
public native String strsignal(int signal);
public native void symlink(String oldPath, String newPath) throws ErrnoException;
diff --git a/luni/src/main/java/libcore/io/StrictLineReader.java b/luni/src/main/java/libcore/io/StrictLineReader.java
index 36556a0..a2e55cc 100644
--- a/luni/src/main/java/libcore/io/StrictLineReader.java
+++ b/luni/src/main/java/libcore/io/StrictLineReader.java
@@ -22,7 +22,7 @@
import java.io.InputStream;
import java.io.IOException;
import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
/**
* Buffers input from an {@link InputStream} for reading lines.
@@ -78,7 +78,7 @@
* @throws IllegalArgumentException for negative or zero {@code capacity}.
*/
public StrictLineReader(InputStream in, int capacity) {
- this(in, capacity, Charsets.US_ASCII);
+ this(in, capacity, StandardCharsets.US_ASCII);
}
/**
@@ -114,8 +114,8 @@
if (capacity < 0) {
throw new IllegalArgumentException("capacity <= 0");
}
- if (!(charset.equals(Charsets.US_ASCII) || charset.equals(Charsets.UTF_8) ||
- charset.equals(Charsets.ISO_8859_1))) {
+ if (!(charset.equals(StandardCharsets.US_ASCII) || charset.equals(StandardCharsets.UTF_8) ||
+ charset.equals(StandardCharsets.ISO_8859_1))) {
throw new IllegalArgumentException("Unsupported encoding");
}
@@ -240,4 +240,3 @@
end = result;
}
}
-
diff --git a/luni/src/main/java/libcore/io/StructStatFs.java b/luni/src/main/java/libcore/io/StructStatFs.java
deleted file mode 100644
index 603dc86..0000000
--- a/luni/src/main/java/libcore/io/StructStatFs.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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 libcore.io;
-
-/**
- * File information returned by fstatfs(2) and statfs(2).
- *
- * TODO: this should be {@code struct statvfs}, but Bionic doesn't support that yet.
- * @hide until the TODO is fixed.
- */
-public final class StructStatFs {
- /** File system block size (used for block counts). */
- public final long f_bsize; /*unsigned long*/
-
- /** Total block count. */
- public final long f_blocks; /*fsblkcnt_t*/
-
- /** Free block count. */
- public final long f_bfree; /*fsblkcnt_t*/
-
- /** Free block count available to non-root. */
- public final long f_bavail; /*fsblkcnt_t*/
-
- /** Total file (inode) count. */
- public final long f_files; /*fsfilcnt_t*/
-
- /** Free file (inode) count. */
- public final long f_ffree; /*fsfilcnt_t*/
-
- /** Maximum filename length. */
- public final long f_namemax; /*unsigned long*/
-
- /** Fundamental file system block size. */
- public final long f_frsize; /*unsigned long*/
-
- StructStatFs(long f_bsize, long f_blocks, long f_bfree, long f_bavail,
- long f_files, long f_ffree, long f_namemax, long f_frsize) {
- this.f_bsize = f_bsize;
- this.f_blocks = f_blocks;
- this.f_bfree = f_bfree;
- this.f_bavail = f_bavail;
- this.f_files = f_files;
- this.f_ffree = f_ffree;
- this.f_namemax = f_namemax;
- this.f_frsize = f_frsize;
- }
-}
diff --git a/luni/src/main/java/libcore/io/StructStatVfs.java b/luni/src/main/java/libcore/io/StructStatVfs.java
new file mode 100644
index 0000000..bb78ff2
--- /dev/null
+++ b/luni/src/main/java/libcore/io/StructStatVfs.java
@@ -0,0 +1,71 @@
+/*
+ * 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 libcore.io;
+
+/**
+ * File information returned by fstatvfs(2) and statvfs(2).
+ */
+public final class StructStatVfs {
+ /** File system block size (used for block counts). */
+ public final long f_bsize; /*unsigned long*/
+
+ /** Fundamental file system block size. */
+ public final long f_frsize; /*unsigned long*/
+
+ /** Total block count. */
+ public final long f_blocks; /*fsblkcnt_t*/
+
+ /** Free block count. */
+ public final long f_bfree; /*fsblkcnt_t*/
+
+ /** Free block count available to non-root. */
+ public final long f_bavail; /*fsblkcnt_t*/
+
+ /** Total file (inode) count. */
+ public final long f_files; /*fsfilcnt_t*/
+
+ /** Free file (inode) count. */
+ public final long f_ffree; /*fsfilcnt_t*/
+
+ /** Free file (inode) count available to non-root. */
+ public final long f_favail; /*fsfilcnt_t*/
+
+ /** File system id. */
+ public final long f_fsid; /*unsigned long*/
+
+ /** Bit mask of ST_* flags. */
+ public final long f_flag; /*unsigned long*/
+
+ /** Maximum filename length. */
+ public final long f_namemax; /*unsigned long*/
+
+ StructStatVfs(long f_bsize, long f_frsize, long f_blocks, long f_bfree, long f_bavail,
+ long f_files, long f_ffree, long f_favail,
+ long f_fsid, long f_flag, long f_namemax) {
+ this.f_bsize = f_bsize;
+ this.f_frsize = f_frsize;
+ this.f_blocks = f_blocks;
+ this.f_bfree = f_bfree;
+ this.f_bavail = f_bavail;
+ this.f_files = f_files;
+ this.f_ffree = f_ffree;
+ this.f_favail = f_favail;
+ this.f_fsid = f_fsid;
+ this.f_flag = f_flag;
+ this.f_namemax = f_namemax;
+ }
+}
diff --git a/luni/src/main/java/libcore/net/UriCodec.java b/luni/src/main/java/libcore/net/UriCodec.java
index 3db95d0..dd18c5f 100644
--- a/luni/src/main/java/libcore/net/UriCodec.java
+++ b/luni/src/main/java/libcore/net/UriCodec.java
@@ -20,7 +20,7 @@
import java.io.ByteArrayOutputStream;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
/**
* Encodes and decodes {@code application/x-www-form-urlencoded} content.
@@ -135,11 +135,11 @@
}
public final void appendEncoded(StringBuilder builder, String s) {
- appendEncoded(builder, s, Charsets.UTF_8, false);
+ appendEncoded(builder, s, StandardCharsets.UTF_8, false);
}
public final void appendPartiallyEncoded(StringBuilder builder, String s) {
- appendEncoded(builder, s, Charsets.UTF_8, true);
+ appendEncoded(builder, s, StandardCharsets.UTF_8, true);
}
/**
@@ -203,7 +203,7 @@
}
public static String decode(String s) {
- return decode(s, false, Charsets.UTF_8, true);
+ return decode(s, false, StandardCharsets.UTF_8, true);
}
private static void appendHex(StringBuilder builder, String s, Charset charset) {
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
deleted file mode 100644
index 70f76b7..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpInputStream.java
+++ /dev/null
@@ -1,107 +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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import libcore.io.Streams;
-
-/**
- * An input stream for the body of an HTTP response.
- *
- * <p>Since a single socket's input stream may be used to read multiple HTTP
- * responses from the same server, subclasses shouldn't close the socket stream.
- *
- * <p>A side effect of reading an HTTP response is that the response cache
- * is populated. If the stream is closed early, that cache entry will be
- * invalidated.
- */
-abstract class AbstractHttpInputStream extends InputStream {
- protected final InputStream in;
- protected final HttpEngine httpEngine;
- private final CacheRequest cacheRequest;
- private final OutputStream cacheBody;
- protected boolean closed;
-
- AbstractHttpInputStream(InputStream in, HttpEngine httpEngine,
- CacheRequest cacheRequest) throws IOException {
- this.in = in;
- this.httpEngine = httpEngine;
-
- OutputStream cacheBody = cacheRequest != null ? cacheRequest.getBody() : null;
-
- // some apps return a null body; for compatibility we treat that like a null cache request
- if (cacheBody == null) {
- cacheRequest = null;
- }
-
- this.cacheBody = cacheBody;
- this.cacheRequest = cacheRequest;
- }
-
- /**
- * read() is implemented using read(byte[], int, int) so subclasses only
- * need to override the latter.
- */
- @Override public final int read() throws IOException {
- return Streams.readSingleByte(this);
- }
-
- protected final void checkNotClosed() throws IOException {
- if (closed) {
- throw new IOException("stream closed");
- }
- }
-
- protected final void cacheWrite(byte[] buffer, int offset, int count) throws IOException {
- if (cacheBody != null) {
- cacheBody.write(buffer, offset, count);
- }
- }
-
- /**
- * Closes the cache entry and makes the socket available for reuse. This
- * should be invoked when the end of the body has been reached.
- */
- protected final void endOfInput(boolean reuseSocket) throws IOException {
- if (cacheRequest != null) {
- cacheBody.close();
- }
- httpEngine.release(reuseSocket);
- }
-
- /**
- * Calls abort on the cache entry and disconnects the socket. This
- * should be invoked when the connection is closed unexpectedly to
- * invalidate the cache entry and to prevent the HTTP connection from
- * being reused. HTTP messages are sent in serial so whenever a message
- * cannot be read to completion, subsequent messages cannot be read
- * either and the connection must be discarded.
- *
- * <p>An earlier implementation skipped the remaining bytes, but this
- * requires that the entire transfer be completed. If the intention was
- * to cancel the transfer, closing the connection is the only solution.
- */
- protected final void unexpectedEndOfInput() {
- if (cacheRequest != null) {
- cacheRequest.abort();
- }
- httpEngine.release(false);
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java b/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
deleted file mode 100644
index 1e1b47b..0000000
--- a/luni/src/main/java/libcore/net/http/AbstractHttpOutputStream.java
+++ /dev/null
@@ -1,40 +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.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * An output stream for the body of an HTTP request.
- *
- * <p>Since a single socket's output stream may be used to write multiple HTTP
- * requests to the same server, subclasses should not close the socket stream.
- */
-abstract class AbstractHttpOutputStream extends OutputStream {
- protected boolean closed;
-
- @Override public final void write(int data) throws IOException {
- write(new byte[] { (byte) data });
- }
-
- protected final void checkNotClosed() throws IOException {
- if (closed) {
- throw new IOException("stream closed");
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/Challenge.java b/luni/src/main/java/libcore/net/http/Challenge.java
deleted file mode 100644
index 0326c17..0000000
--- a/luni/src/main/java/libcore/net/http/Challenge.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 libcore.net.http;
-
-/**
- * An RFC 2617 challenge.
- *
- * @hide
- */
-public final class Challenge {
- final String scheme;
- final String realm;
-
- public Challenge(String scheme, String realm) {
- this.scheme = scheme;
- this.realm = realm;
- }
-
- @Override public boolean equals(Object o) {
- return o instanceof Challenge
- && ((Challenge) o).scheme.equals(scheme)
- && ((Challenge) o).realm.equals(realm);
- }
-
- @Override public int hashCode() {
- return scheme.hashCode() + 31 * realm.hashCode();
- }
-
- @Override public String toString() {
- return "Challenge[" + scheme + " " + realm + "]";
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java b/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
deleted file mode 100644
index 91cff7a..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedInputStream.java
+++ /dev/null
@@ -1,114 +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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-import libcore.io.Streams;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies.
- */
-final class ChunkedInputStream extends AbstractHttpInputStream {
- private static final int MIN_LAST_CHUNK_LENGTH = "\r\n0\r\n\r\n".length();
- private static final int NO_CHUNK_YET = -1;
- private int bytesRemainingInChunk = NO_CHUNK_YET;
- private boolean hasMoreChunks = true;
-
- ChunkedInputStream(InputStream is, CacheRequest cacheRequest,
- HttpEngine httpEngine) throws IOException {
- super(is, httpEngine, cacheRequest);
- }
-
- @Override public int read(byte[] buffer, int offset, int count) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
- checkNotClosed();
-
- if (!hasMoreChunks) {
- return -1;
- }
- if (bytesRemainingInChunk == 0 || bytesRemainingInChunk == NO_CHUNK_YET) {
- readChunkSize();
- if (!hasMoreChunks) {
- return -1;
- }
- }
- int read = in.read(buffer, offset, Math.min(count, bytesRemainingInChunk));
- if (read == -1) {
- unexpectedEndOfInput(); // the server didn't supply the promised chunk length
- throw new IOException("unexpected end of stream");
- }
- bytesRemainingInChunk -= read;
- cacheWrite(buffer, offset, read);
-
- /*
- * If we're at the end of a chunk and the next chunk size is readable,
- * read it! Reading the last chunk causes the underlying connection to
- * be recycled and we want to do that as early as possible. Otherwise
- * self-delimiting streams like gzip will never be recycled.
- * http://code.google.com/p/android/issues/detail?id=7059
- */
- if (bytesRemainingInChunk == 0 && in.available() >= MIN_LAST_CHUNK_LENGTH) {
- readChunkSize();
- }
-
- return read;
- }
-
- private void readChunkSize() throws IOException {
- // read the suffix of the previous chunk
- if (bytesRemainingInChunk != NO_CHUNK_YET) {
- Streams.readAsciiLine(in);
- }
- String chunkSizeString = Streams.readAsciiLine(in);
- int index = chunkSizeString.indexOf(";");
- if (index != -1) {
- chunkSizeString = chunkSizeString.substring(0, index);
- }
- try {
- bytesRemainingInChunk = Integer.parseInt(chunkSizeString.trim(), 16);
- } catch (NumberFormatException e) {
- throw new IOException("Expected a hex chunk size, but was " + chunkSizeString);
- }
- if (bytesRemainingInChunk == 0) {
- hasMoreChunks = false;
- httpEngine.readTrailers();
- endOfInput(true);
- }
- }
-
- @Override public int available() throws IOException {
- checkNotClosed();
- if (!hasMoreChunks || bytesRemainingInChunk == NO_CHUNK_YET) {
- return 0;
- }
- return Math.min(in.available(), bytesRemainingInChunk);
- }
-
- @Override public void close() throws IOException {
- if (closed) {
- return;
- }
-
- closed = true;
- if (hasMoreChunks) {
- unexpectedEndOfInput();
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java b/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
deleted file mode 100644
index db65f7b..0000000
--- a/luni/src/main/java/libcore/net/http/ChunkedOutputStream.java
+++ /dev/null
@@ -1,133 +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.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with alternating chunk sizes and chunk bodies. Chunks are
- * buffered until {@code maxChunkLength} bytes are ready, at which point the
- * chunk is written and the buffer is cleared.
- */
-final class ChunkedOutputStream extends AbstractHttpOutputStream {
- private static final byte[] CRLF = { '\r', '\n' };
- private static final byte[] HEX_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
- };
- private static final byte[] FINAL_CHUNK = new byte[] { '0', '\r', '\n', '\r', '\n' };
-
- /** Scratch space for up to 8 hex digits, and then a constant CRLF */
- private final byte[] hex = { 0, 0, 0, 0, 0, 0, 0, 0, '\r', '\n' };
-
- private final OutputStream socketOut;
- private final int maxChunkLength;
- private final ByteArrayOutputStream bufferedChunk;
-
-
- public ChunkedOutputStream(OutputStream socketOut, int maxChunkLength) {
- this.socketOut = socketOut;
- this.maxChunkLength = Math.max(1, dataLength(maxChunkLength));
- this.bufferedChunk = new ByteArrayOutputStream(maxChunkLength);
- }
-
- /**
- * Returns the amount of data that can be transmitted in a chunk whose total
- * length (data+headers) is {@code dataPlusHeaderLength}. This is presumably
- * useful to match sizes with wire-protocol packets.
- */
- private int dataLength(int dataPlusHeaderLength) {
- int headerLength = 4; // "\r\n" after the size plus another "\r\n" after the data
- for (int i = dataPlusHeaderLength - headerLength; i > 0; i >>= 4) {
- headerLength++;
- }
- return dataPlusHeaderLength - headerLength;
- }
-
- @Override public synchronized void write(byte[] buffer, int offset, int count)
- throws IOException {
- checkNotClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
-
- while (count > 0) {
- int numBytesWritten;
-
- if (bufferedChunk.size() > 0 || count < maxChunkLength) {
- // fill the buffered chunk and then maybe write that to the stream
- numBytesWritten = Math.min(count, maxChunkLength - bufferedChunk.size());
- // TODO: skip unnecessary copies from buffer->bufferedChunk?
- bufferedChunk.write(buffer, offset, numBytesWritten);
- if (bufferedChunk.size() == maxChunkLength) {
- writeBufferedChunkToSocket();
- }
-
- } else {
- // write a single chunk of size maxChunkLength to the stream
- numBytesWritten = maxChunkLength;
- writeHex(numBytesWritten);
- socketOut.write(buffer, offset, numBytesWritten);
- socketOut.write(CRLF);
- }
-
- offset += numBytesWritten;
- count -= numBytesWritten;
- }
- }
-
- /**
- * Equivalent to, but cheaper than writing Integer.toHexString().getBytes()
- * followed by CRLF.
- */
- private void writeHex(int i) throws IOException {
- int cursor = 8;
- do {
- hex[--cursor] = HEX_DIGITS[i & 0xf];
- } while ((i >>>= 4) != 0);
- socketOut.write(hex, cursor, hex.length - cursor);
- }
-
- @Override public synchronized void flush() throws IOException {
- if (closed) {
- return; // don't throw; this stream might have been closed on the caller's behalf
- }
- writeBufferedChunkToSocket();
- socketOut.flush();
- }
-
- @Override public synchronized void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- writeBufferedChunkToSocket();
- socketOut.write(FINAL_CHUNK);
- }
-
- private void writeBufferedChunkToSocket() throws IOException {
- int size = bufferedChunk.size();
- if (size <= 0) {
- return;
- }
-
- writeHex(size);
- bufferedChunk.writeTo(socketOut);
- bufferedChunk.reset();
- socketOut.write(CRLF);
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
deleted file mode 100644
index 1091af7..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthInputStream.java
+++ /dev/null
@@ -1,72 +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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length specified in advance.
- */
-final class FixedLengthInputStream extends AbstractHttpInputStream {
- private int bytesRemaining;
-
- public FixedLengthInputStream(InputStream is, CacheRequest cacheRequest,
- HttpEngine httpEngine, int length) throws IOException {
- super(is, httpEngine, cacheRequest);
- bytesRemaining = length;
- if (bytesRemaining == 0) {
- endOfInput(true);
- }
- }
-
- @Override public int read(byte[] buffer, int offset, int count) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
- checkNotClosed();
- if (bytesRemaining == 0) {
- return -1;
- }
- int read = in.read(buffer, offset, Math.min(count, bytesRemaining));
- if (read == -1) {
- unexpectedEndOfInput(); // the server didn't supply the promised content length
- throw new IOException("unexpected end of stream");
- }
- bytesRemaining -= read;
- cacheWrite(buffer, offset, read);
- if (bytesRemaining == 0) {
- endOfInput(true);
- }
- return read;
- }
-
- @Override public int available() throws IOException {
- checkNotClosed();
- return bytesRemaining == 0 ? 0 : Math.min(in.available(), bytesRemaining);
- }
-
- @Override public void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- if (bytesRemaining != 0) {
- unexpectedEndOfInput();
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java b/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
deleted file mode 100644
index 461eed9..0000000
--- a/luni/src/main/java/libcore/net/http/FixedLengthOutputStream.java
+++ /dev/null
@@ -1,61 +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.net.http;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP body with a fixed length known in advance.
- */
-final class FixedLengthOutputStream extends AbstractHttpOutputStream {
- private final OutputStream socketOut;
- private int bytesRemaining;
-
- public FixedLengthOutputStream(OutputStream socketOut, int bytesRemaining) {
- this.socketOut = socketOut;
- this.bytesRemaining = bytesRemaining;
- }
-
- @Override public void write(byte[] buffer, int offset, int count) throws IOException {
- checkNotClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
- if (count > bytesRemaining) {
- throw new IOException("expected " + bytesRemaining + " bytes but received " + count);
- }
- socketOut.write(buffer, offset, count);
- bytesRemaining -= count;
- }
-
- @Override public void flush() throws IOException {
- if (closed) {
- return; // don't throw; this stream might have been closed on the caller's behalf
- }
- socketOut.flush();
- }
-
- @Override public void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- if (bytesRemaining > 0) {
- throw new IOException("unexpected end of stream");
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HeaderParser.java b/luni/src/main/java/libcore/net/http/HeaderParser.java
deleted file mode 100644
index 8d5770e..0000000
--- a/luni/src/main/java/libcore/net/http/HeaderParser.java
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- * 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 libcore.net.http;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @hide
- */
-public final class HeaderParser {
-
- public interface CacheControlHandler {
- void handle(String directive, String parameter);
- }
-
- /**
- * Parse a comma-separated list of cache control header values.
- */
- public static void parseCacheControl(String value, CacheControlHandler handler) {
- int pos = 0;
- while (pos < value.length()) {
- int tokenStart = pos;
- pos = skipUntil(value, pos, "=,");
- String directive = value.substring(tokenStart, pos).trim();
-
- if (pos == value.length() || value.charAt(pos) == ',') {
- pos++; // consume ',' (if necessary)
- handler.handle(directive, null);
- continue;
- }
-
- pos++; // consume '='
- pos = skipWhitespace(value, pos);
-
- String parameter;
-
- // quoted string
- if (pos < value.length() && value.charAt(pos) == '\"') {
- pos++; // consume '"' open quote
- int parameterStart = pos;
- pos = skipUntil(value, pos, "\"");
- parameter = value.substring(parameterStart, pos);
- pos++; // consume '"' close quote (if necessary)
-
- // unquoted string
- } else {
- int parameterStart = pos;
- pos = skipUntil(value, pos, ",");
- parameter = value.substring(parameterStart, pos).trim();
- }
-
- handler.handle(directive, parameter);
- }
- }
-
- /**
- * Parse RFC 2617 challenges. This API is only interested in the scheme
- * name and realm.
- */
- public static List<Challenge> parseChallenges(
- RawHeaders responseHeaders, String challengeHeader) {
- /*
- * auth-scheme = token
- * auth-param = token "=" ( token | quoted-string )
- * challenge = auth-scheme 1*SP 1#auth-param
- * realm = "realm" "=" realm-value
- * realm-value = quoted-string
- */
- List<Challenge> result = new ArrayList<Challenge>();
- for (int h = 0; h < responseHeaders.length(); h++) {
- if (!challengeHeader.equalsIgnoreCase(responseHeaders.getFieldName(h))) {
- continue;
- }
- String value = responseHeaders.getValue(h);
- int pos = 0;
- while (pos < value.length()) {
- int tokenStart = pos;
- pos = skipUntil(value, pos, " ");
-
- String scheme = value.substring(tokenStart, pos).trim();
- pos = skipWhitespace(value, pos);
-
- // TODO: This currently only handles schemes with a 'realm' parameter;
- // It needs to be fixed to handle any scheme and any parameters
- // http://code.google.com/p/android/issues/detail?id=11140
-
- if (!value.regionMatches(pos, "realm=\"", 0, "realm=\"".length())) {
- break; // unexpected challenge parameter; give up
- }
-
- pos += "realm=\"".length();
- int realmStart = pos;
- pos = skipUntil(value, pos, "\"");
- String realm = value.substring(realmStart, pos);
- pos++; // consume '"' close quote
- pos = skipUntil(value, pos, ",");
- pos++; // consume ',' comma
- pos = skipWhitespace(value, pos);
- result.add(new Challenge(scheme, realm));
- }
- }
- return result;
- }
-
- /**
- * Returns the next index in {@code input} at or after {@code pos} that
- * contains a character from {@code characters}. Returns the input length if
- * none of the requested characters can be found.
- */
- private static int skipUntil(String input, int pos, String characters) {
- for (; pos < input.length(); pos++) {
- if (characters.indexOf(input.charAt(pos)) != -1) {
- break;
- }
- }
- return pos;
- }
-
- /**
- * Returns the next non-whitespace character in {@code input} that is white
- * space. Result is undefined if input contains newline characters.
- */
- private static int skipWhitespace(String input, int pos) {
- for (; pos < input.length(); pos++) {
- char c = input.charAt(pos);
- if (c != ' ' && c != '\t') {
- break;
- }
- }
- return pos;
- }
-
- /**
- * Returns {@code value} as a positive integer, or 0 if it is negative, or
- * -1 if it cannot be parsed.
- */
- public static int parseSeconds(String value) {
- try {
- long seconds = Long.parseLong(value);
- if (seconds > Integer.MAX_VALUE) {
- return Integer.MAX_VALUE;
- } else if (seconds < 0) {
- return 0;
- } else {
- return (int) seconds;
- }
- } catch (NumberFormatException e) {
- return -1;
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnection.java b/luni/src/main/java/libcore/net/http/HttpConnection.java
deleted file mode 100644
index 4a6e65d..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnection.java
+++ /dev/null
@@ -1,343 +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.net.http;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.ProxySelector;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.SocketException;
-import java.net.URI;
-import java.net.UnknownHostException;
-import java.util.List;
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.util.Objects;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl;
-
-/**
- * Holds the sockets and streams of an HTTP or HTTPS connection, which may be
- * used for multiple HTTP request/response exchanges. Connections may be direct
- * to the origin server or via a proxy. Create an instance using the {@link
- * Address} inner class.
- *
- * <p>Do not confuse this class with the misnamed {@code HttpURLConnection},
- * which isn't so much a connection as a single request/response pair.
- */
-final class HttpConnection {
- private final Address address;
- private final Socket socket;
- private InputStream inputStream;
- private OutputStream outputStream;
- private SSLSocket unverifiedSocket;
- private SSLSocket sslSocket;
- private InputStream sslInputStream;
- private OutputStream sslOutputStream;
- private boolean recycled = false;
-
- private HttpConnection(Address config, int connectTimeout) throws IOException {
- this.address = config;
-
- /*
- * Try each of the host's addresses for best behavior in mixed IPv4/IPv6
- * environments. See http://b/2876927
- * TODO: add a hidden method so that Socket.tryAllAddresses can does this for us
- */
- Socket socketCandidate = null;
- InetAddress[] addresses = InetAddress.getAllByName(config.socketHost);
- for (int i = 0; i < addresses.length; i++) {
- socketCandidate = (config.proxy != null && config.proxy.type() != Proxy.Type.HTTP)
- ? new Socket(config.proxy)
- : new Socket();
- try {
- socketCandidate.connect(
- new InetSocketAddress(addresses[i], config.socketPort), connectTimeout);
- break;
- } catch (IOException e) {
- if (i == addresses.length - 1) {
- throw e;
- }
- }
- }
-
- this.socket = socketCandidate;
- }
-
- public static HttpConnection connect(URI uri, SSLSocketFactory sslSocketFactory,
- Proxy proxy, boolean requiresTunnel, int connectTimeout) throws IOException {
- /*
- * Try an explicitly-specified proxy.
- */
- if (proxy != null) {
- Address address = (proxy.type() == Proxy.Type.DIRECT)
- ? new Address(uri, sslSocketFactory)
- : new Address(uri, sslSocketFactory, proxy, requiresTunnel);
- return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
- }
-
- /*
- * Try connecting to each of the proxies provided by the ProxySelector
- * until a connection succeeds.
- */
- ProxySelector selector = ProxySelector.getDefault();
- List<Proxy> proxyList = selector.select(uri);
- if (proxyList != null) {
- for (Proxy selectedProxy : proxyList) {
- if (selectedProxy.type() == Proxy.Type.DIRECT) {
- // the same as NO_PROXY
- // TODO: if the selector recommends a direct connection, attempt that?
- continue;
- }
- try {
- Address address = new Address(uri, sslSocketFactory,
- selectedProxy, requiresTunnel);
- return HttpConnectionPool.INSTANCE.get(address, connectTimeout);
- } catch (IOException e) {
- // failed to connect, tell it to the selector
- selector.connectFailed(uri, selectedProxy.address(), e);
- }
- }
- }
-
- /*
- * Try a direct connection. If this fails, this method will throw.
- */
- return HttpConnectionPool.INSTANCE.get(new Address(uri, sslSocketFactory), connectTimeout);
- }
-
- public void closeSocketAndStreams() {
- IoUtils.closeQuietly(sslOutputStream);
- IoUtils.closeQuietly(sslInputStream);
- IoUtils.closeQuietly(sslSocket);
- IoUtils.closeQuietly(outputStream);
- IoUtils.closeQuietly(inputStream);
- IoUtils.closeQuietly(socket);
- }
-
- public void setSoTimeout(int readTimeout) throws SocketException {
- socket.setSoTimeout(readTimeout);
- }
-
- public OutputStream getOutputStream() throws IOException {
- if (sslSocket != null) {
- if (sslOutputStream == null) {
- sslOutputStream = sslSocket.getOutputStream();
- }
- return sslOutputStream;
- } else if(outputStream == null) {
- outputStream = socket.getOutputStream();
- }
- return outputStream;
- }
-
- public InputStream getInputStream() throws IOException {
- if (sslSocket != null) {
- if (sslInputStream == null) {
- sslInputStream = sslSocket.getInputStream();
- }
- return sslInputStream;
- } else if (inputStream == null) {
- /*
- * Buffer the socket stream to permit efficient parsing of HTTP
- * headers and chunk sizes. Benchmarks suggest 128 is sufficient.
- * We cannot buffer when setting up a tunnel because we may consume
- * bytes intended for the SSL socket.
- */
- int bufferSize = 128;
- inputStream = address.requiresTunnel
- ? socket.getInputStream()
- : new BufferedInputStream(socket.getInputStream(), bufferSize);
- }
- return inputStream;
- }
-
- protected Socket getSocket() {
- return sslSocket != null ? sslSocket : socket;
- }
-
- public Address getAddress() {
- return address;
- }
-
- /**
- * Create an {@code SSLSocket} and perform the SSL handshake
- * (performing certificate validation.
- *
- * @param sslSocketFactory Source of new {@code SSLSocket} instances.
- * @param tlsTolerant If true, assume server can handle common
- * TLS extensions and SSL deflate compression. If false, use
- * an SSL3 only fallback mode without compression.
- */
- public void setupSecureSocket(SSLSocketFactory sslSocketFactory, boolean tlsTolerant)
- throws IOException {
- // create the wrapper over connected socket
- unverifiedSocket = (SSLSocket) sslSocketFactory.createSocket(socket,
- address.uriHost, address.uriPort, true /* autoClose */);
- // tlsTolerant mimics Chrome's behavior
- if (tlsTolerant && unverifiedSocket instanceof OpenSSLSocketImpl) {
- OpenSSLSocketImpl openSslSocket = (OpenSSLSocketImpl) unverifiedSocket;
- openSslSocket.setUseSessionTickets(true);
- openSslSocket.setHostname(address.uriHost);
- // use SSLSocketFactory default enabled protocols
- } else {
- unverifiedSocket.setEnabledProtocols(new String [] { "SSLv3" });
- }
- // force handshake, which can throw
- unverifiedSocket.startHandshake();
- }
-
- /**
- * Return an {@code SSLSocket} that is not only connected but has
- * also passed hostname verification.
- *
- * @param hostnameVerifier Used to verify the hostname we
- * connected to is an acceptable match for the peer certificate
- * chain of the SSLSession.
- */
- public SSLSocket verifySecureSocketHostname(HostnameVerifier hostnameVerifier)
- throws IOException {
- if (!hostnameVerifier.verify(address.uriHost, unverifiedSocket.getSession())) {
- throw new IOException("Hostname '" + address.uriHost + "' was not verified");
- }
- sslSocket = unverifiedSocket;
- return sslSocket;
- }
-
- /**
- * Return an {@code SSLSocket} if already connected, otherwise null.
- */
- public SSLSocket getSecureSocketIfConnected() {
- return sslSocket;
- }
-
- /**
- * Returns true if this connection has been used to satisfy an earlier
- * HTTP request/response pair.
- */
- public boolean isRecycled() {
- return recycled;
- }
-
- public void setRecycled() {
- this.recycled = true;
- }
-
- /**
- * Returns true if this connection is eligible to be reused for another
- * request/response pair.
- */
- protected boolean isEligibleForRecycling() {
- return !socket.isClosed()
- && !socket.isInputShutdown()
- && !socket.isOutputShutdown();
- }
-
- /**
- * This address has two parts: the address we connect to directly and the
- * origin address of the resource. These are the same unless a proxy is
- * being used. It also includes the SSL socket factory so that a socket will
- * not be reused if its SSL configuration is different.
- */
- public static final class Address {
- private final Proxy proxy;
- private final boolean requiresTunnel;
- private final String uriHost;
- private final int uriPort;
- private final String socketHost;
- private final int socketPort;
- private final SSLSocketFactory sslSocketFactory;
-
- public Address(URI uri, SSLSocketFactory sslSocketFactory) throws UnknownHostException {
- this.proxy = null;
- this.requiresTunnel = false;
- this.uriHost = uri.getHost();
- this.uriPort = uri.getEffectivePort();
- this.sslSocketFactory = sslSocketFactory;
- this.socketHost = uriHost;
- this.socketPort = uriPort;
- if (uriHost == null) {
- throw new UnknownHostException(uri.toString());
- }
- }
-
- /**
- * @param requiresTunnel true if the HTTP connection needs to tunnel one
- * protocol over another, such as when using HTTPS through an HTTP
- * proxy. When doing so, we must avoid buffering bytes intended for
- * the higher-level protocol.
- */
- public Address(URI uri, SSLSocketFactory sslSocketFactory,
- Proxy proxy, boolean requiresTunnel) throws UnknownHostException {
- this.proxy = proxy;
- this.requiresTunnel = requiresTunnel;
- this.uriHost = uri.getHost();
- this.uriPort = uri.getEffectivePort();
- this.sslSocketFactory = sslSocketFactory;
-
- SocketAddress proxyAddress = proxy.address();
- if (!(proxyAddress instanceof InetSocketAddress)) {
- throw new IllegalArgumentException("Proxy.address() is not an InetSocketAddress: "
- + proxyAddress.getClass());
- }
- InetSocketAddress proxySocketAddress = (InetSocketAddress) proxyAddress;
- this.socketHost = proxySocketAddress.getHostName();
- this.socketPort = proxySocketAddress.getPort();
- if (uriHost == null) {
- throw new UnknownHostException(uri.toString());
- }
- }
-
- public Proxy getProxy() {
- return proxy;
- }
-
- @Override public boolean equals(Object other) {
- if (other instanceof Address) {
- Address that = (Address) other;
- return Objects.equal(this.proxy, that.proxy)
- && this.uriHost.equals(that.uriHost)
- && this.uriPort == that.uriPort
- && Objects.equal(this.sslSocketFactory, that.sslSocketFactory)
- && this.requiresTunnel == that.requiresTunnel;
- }
- return false;
- }
-
- @Override public int hashCode() {
- int result = 17;
- result = 31 * result + uriHost.hashCode();
- result = 31 * result + uriPort;
- result = 31 * result + (sslSocketFactory != null ? sslSocketFactory.hashCode() : 0);
- result = 31 * result + (proxy != null ? proxy.hashCode() : 0);
- result = 31 * result + (requiresTunnel ? 1 : 0);
- return result;
- }
-
- public HttpConnection connect(int connectTimeout) throws IOException {
- return new HttpConnection(this, connectTimeout);
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java b/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
deleted file mode 100644
index 1f5f4d9..0000000
--- a/luni/src/main/java/libcore/net/http/HttpConnectionPool.java
+++ /dev/null
@@ -1,120 +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.net.http;
-
-import dalvik.system.SocketTagger;
-import java.io.IOException;
-import java.net.Socket;
-import java.net.SocketException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * A pool of HTTP connections. This class exposes its tuning parameters as
- * system properties:
- * <ul>
- * <li>{@code http.keepAlive} true if HTTP connections should be pooled at
- * all. Default is true.
- * <li>{@code http.maxConnections} maximum number of connections to each URI.
- * Default is 5.
- * </ul>
- *
- * <p>This class <i>doesn't</i> adjust its configuration as system properties
- * are changed. This assumes that the applications that set these parameters do
- * so before making HTTP connections, and that this class is initialized lazily.
- */
-final class HttpConnectionPool {
-
- public static final HttpConnectionPool INSTANCE = new HttpConnectionPool();
-
- private final int maxConnections;
- private final HashMap<HttpConnection.Address, List<HttpConnection>> connectionPool
- = new HashMap<HttpConnection.Address, List<HttpConnection>>();
-
- private HttpConnectionPool() {
- String keepAlive = System.getProperty("http.keepAlive");
- if (keepAlive != null && !Boolean.parseBoolean(keepAlive)) {
- maxConnections = 0;
- return;
- }
-
- String maxConnectionsString = System.getProperty("http.maxConnections");
- this.maxConnections = maxConnectionsString != null
- ? Integer.parseInt(maxConnectionsString)
- : 5;
- }
-
- public HttpConnection get(HttpConnection.Address address, int connectTimeout)
- throws IOException {
- // First try to reuse an existing HTTP connection.
- synchronized (connectionPool) {
- List<HttpConnection> connections = connectionPool.get(address);
- while (connections != null) {
- HttpConnection connection = connections.remove(connections.size() - 1);
- if (connections.isEmpty()) {
- connectionPool.remove(address);
- connections = null;
- }
- if (connection.isEligibleForRecycling()) {
- // Since Socket is recycled, re-tag before using
- Socket socket = connection.getSocket();
- SocketTagger.get().tag(socket);
- return connection;
- }
- }
- }
-
- /*
- * We couldn't find a reusable connection, so we need to create a new
- * connection. We're careful not to do so while holding a lock!
- */
- return address.connect(connectTimeout);
- }
-
- public void recycle(HttpConnection connection) {
- Socket socket = connection.getSocket();
- try {
- SocketTagger.get().untag(socket);
- } catch (SocketException e) {
- // When unable to remove tagging, skip recycling and close
- System.logW("Unable to untagSocket(): " + e);
- connection.closeSocketAndStreams();
- return;
- }
-
- if (maxConnections > 0 && connection.isEligibleForRecycling()) {
- HttpConnection.Address address = connection.getAddress();
- synchronized (connectionPool) {
- List<HttpConnection> connections = connectionPool.get(address);
- if (connections == null) {
- connections = new ArrayList<HttpConnection>();
- connectionPool.put(address, connections);
- }
- if (connections.size() < maxConnections) {
- connection.setRecycled();
- connections.add(connection);
- return; // keep the connection open
- }
- }
- }
-
- // don't close streams while holding a lock!
- connection.closeSocketAndStreams();
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpEngine.java b/luni/src/main/java/libcore/net/http/HttpEngine.java
deleted file mode 100644
index 8d81c38..0000000
--- a/luni/src/main/java/libcore/net/http/HttpEngine.java
+++ /dev/null
@@ -1,852 +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.net.http;
-
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.Proxy;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-import javax.net.ssl.SSLSocketFactory;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-import libcore.util.EmptyArray;
-
-/**
- * Handles a single HTTP request/response pair. Each HTTP engine follows this
- * lifecycle:
- * <ol>
- * <li>It is created.
- * <li>The HTTP request message is sent with sendRequest(). Once the request
- * is sent it is an error to modify the request headers. After
- * sendRequest() has been called the request body can be written to if
- * it exists.
- * <li>The HTTP response message is read with readResponse(). After the
- * response has been read the response headers and body can be read.
- * All responses have a response body input stream, though in some
- * instances this stream is empty.
- * </ol>
- *
- * <p>The request and response may be served by the HTTP response cache, by the
- * network, or by both in the event of a conditional GET.
- *
- * <p>This class may hold a socket connection that needs to be released or
- * recycled. By default, this socket connection is held when the last byte of
- * the response is consumed. To release the connection when it is no longer
- * required, use {@link #automaticallyReleaseConnectionToPool()}.
- */
-public class HttpEngine {
- private static final CacheResponse GATEWAY_TIMEOUT_RESPONSE = new CacheResponse() {
- @Override public Map<String, List<String>> getHeaders() throws IOException {
- Map<String, List<String>> result = new HashMap<String, List<String>>();
- result.put(null, Collections.singletonList("HTTP/1.1 504 Gateway Timeout"));
- return result;
- }
- @Override public InputStream getBody() throws IOException {
- return new ByteArrayInputStream(EmptyArray.BYTE);
- }
- };
-
- /**
- * The maximum number of bytes to buffer when sending headers and a request
- * body. When the headers and body can be sent in a single write, the
- * request completes sooner. In one WiFi benchmark, using a large enough
- * buffer sped up some uploads by half.
- */
- private static final int MAX_REQUEST_BUFFER_LENGTH = 32768;
-
- public static final int DEFAULT_CHUNK_LENGTH = 1024;
-
- public static final String OPTIONS = "OPTIONS";
- public static final String GET = "GET";
- public static final String HEAD = "HEAD";
- public static final String POST = "POST";
- public static final String PUT = "PUT";
- public static final String DELETE = "DELETE";
- public static final String TRACE = "TRACE";
- public static final String CONNECT = "CONNECT";
-
- public static final int HTTP_CONTINUE = 100;
-
- /**
- * HTTP 1.1 doesn't specify how many redirects to follow, but HTTP/1.0
- * recommended 5. http://www.w3.org/Protocols/HTTP/1.0/spec.html#Code3xx
- */
- public static final int MAX_REDIRECTS = 5;
-
- protected final HttpURLConnectionImpl policy;
-
- protected final String method;
-
- private ResponseSource responseSource;
-
- protected HttpConnection connection;
- private InputStream socketIn;
- private OutputStream socketOut;
-
- /**
- * This stream buffers the request headers and the request body when their
- * combined size is less than MAX_REQUEST_BUFFER_LENGTH. By combining them
- * we can save socket writes, which in turn saves a packet transmission.
- * This is socketOut if the request size is large or unknown.
- */
- private OutputStream requestOut;
- private AbstractHttpOutputStream requestBodyOut;
-
- private InputStream responseBodyIn;
-
- private final ResponseCache responseCache = ResponseCache.getDefault();
- private CacheResponse cacheResponse;
- private CacheRequest cacheRequest;
-
- /** The time when the request headers were written, or -1 if they haven't been written yet. */
- private long sentRequestMillis = -1;
-
- /**
- * True if this client added an "Accept-Encoding: gzip" header field and is
- * therefore responsible for also decompressing the transfer stream.
- */
- private boolean transparentGzip;
-
- boolean sendChunked;
-
- /**
- * The version this client will use. Either 0 for HTTP/1.0, or 1 for
- * HTTP/1.1. Upon receiving a non-HTTP/1.1 response, this client
- * automatically sets its version to HTTP/1.0.
- */
- // TODO: is HTTP minor version tracked across HttpEngines?
- private int httpMinorVersion = 1; // Assume HTTP/1.1
-
- private final URI uri;
-
- private final RequestHeaders requestHeaders;
-
- /** Null until a response is received from the network or the cache */
- private ResponseHeaders responseHeaders;
-
- /*
- * The cache response currently being validated on a conditional get. Null
- * if the cached response doesn't exist or doesn't need validation. If the
- * conditional get succeeds, these will be used for the response headers and
- * body. If it fails, these be closed and set to null.
- */
- private ResponseHeaders cachedResponseHeaders;
- private InputStream cachedResponseBody;
-
- /**
- * True if the socket connection should be released to the connection pool
- * when the response has been fully read.
- */
- private boolean automaticallyReleaseConnectionToPool;
-
- /** True if the socket connection is no longer needed by this engine. */
- private boolean connectionReleased;
-
- /**
- * @param requestHeaders the client's supplied request headers. This class
- * creates a private copy that it can mutate.
- * @param connection the connection used for an intermediate response
- * immediately prior to this request/response pair, such as a same-host
- * redirect. This engine assumes ownership of the connection and must
- * release it when it is unneeded.
- */
- public HttpEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
- HttpConnection connection, RetryableOutputStream requestBodyOut) throws IOException {
- this.policy = policy;
- this.method = method;
- this.connection = connection;
- this.requestBodyOut = requestBodyOut;
-
- try {
- uri = policy.getURL().toURILenient();
- } catch (URISyntaxException e) {
- throw new IOException(e);
- }
-
- this.requestHeaders = new RequestHeaders(uri, new RawHeaders(requestHeaders));
- }
-
- public URI getUri() {
- return uri;
- }
-
- /**
- * Figures out what the response source will be, and opens a socket to that
- * source if necessary. Prepares the request headers and gets ready to start
- * writing the request body if it exists.
- */
- public final void sendRequest() throws IOException {
- if (responseSource != null) {
- return;
- }
-
- prepareRawRequestHeaders();
- initResponseSource();
- if (responseCache instanceof ExtendedResponseCache) {
- ((ExtendedResponseCache) responseCache).trackResponse(responseSource);
- }
-
- /*
- * The raw response source may require the network, but the request
- * headers may forbid network use. In that case, dispose of the network
- * response and use a GATEWAY_TIMEOUT response instead, as specified
- * by http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4.
- */
- if (requestHeaders.isOnlyIfCached() && responseSource.requiresConnection()) {
- if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
- IoUtils.closeQuietly(cachedResponseBody);
- }
- this.responseSource = ResponseSource.CACHE;
- this.cacheResponse = GATEWAY_TIMEOUT_RESPONSE;
- RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(cacheResponse.getHeaders());
- setResponse(new ResponseHeaders(uri, rawResponseHeaders), cacheResponse.getBody());
- }
-
- if (responseSource.requiresConnection()) {
- sendSocketRequest();
- } else if (connection != null) {
- HttpConnectionPool.INSTANCE.recycle(connection);
- connection = null;
- }
- }
-
- /**
- * Initialize the source for this response. It may be corrected later if the
- * request headers forbids network use.
- */
- private void initResponseSource() throws IOException {
- responseSource = ResponseSource.NETWORK;
- if (!policy.getUseCaches() || responseCache == null) {
- return;
- }
-
- CacheResponse candidate = responseCache.get(uri, method,
- requestHeaders.getHeaders().toMultimap());
- if (candidate == null) {
- return;
- }
-
- Map<String, List<String>> responseHeadersMap = candidate.getHeaders();
- cachedResponseBody = candidate.getBody();
- if (!acceptCacheResponseType(candidate)
- || responseHeadersMap == null
- || cachedResponseBody == null) {
- IoUtils.closeQuietly(cachedResponseBody);
- return;
- }
-
- RawHeaders rawResponseHeaders = RawHeaders.fromMultimap(responseHeadersMap);
- cachedResponseHeaders = new ResponseHeaders(uri, rawResponseHeaders);
- long now = System.currentTimeMillis();
- this.responseSource = cachedResponseHeaders.chooseResponseSource(now, requestHeaders);
- if (responseSource == ResponseSource.CACHE) {
- this.cacheResponse = candidate;
- setResponse(cachedResponseHeaders, cachedResponseBody);
- } else if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
- this.cacheResponse = candidate;
- } else if (responseSource == ResponseSource.NETWORK) {
- IoUtils.closeQuietly(cachedResponseBody);
- } else {
- throw new AssertionError();
- }
- }
-
- private void sendSocketRequest() throws IOException {
- if (connection == null) {
- connect();
- }
-
- if (socketOut != null || requestOut != null || socketIn != null) {
- throw new IllegalStateException();
- }
-
- socketOut = connection.getOutputStream();
- requestOut = socketOut;
- socketIn = connection.getInputStream();
-
- if (hasRequestBody()) {
- initRequestBodyOut();
- }
- }
-
- /**
- * Connect to the origin server either directly or via a proxy.
- */
- protected void connect() throws IOException {
- if (connection == null) {
- connection = openSocketConnection();
- }
- }
-
- protected final HttpConnection openSocketConnection() throws IOException {
- HttpConnection result = HttpConnection.connect(uri, getSslSocketFactory(),
- policy.getProxy(), requiresTunnel(), policy.getConnectTimeout());
- Proxy proxy = result.getAddress().getProxy();
- if (proxy != null) {
- policy.setProxy(proxy);
- }
- result.setSoTimeout(policy.getReadTimeout());
- return result;
- }
-
- protected void initRequestBodyOut() throws IOException {
- int chunkLength = policy.getChunkLength();
- if (chunkLength > 0 || requestHeaders.isChunked()) {
- sendChunked = true;
- if (chunkLength == -1) {
- chunkLength = DEFAULT_CHUNK_LENGTH;
- }
- }
-
- if (socketOut == null) {
- throw new IllegalStateException("No socket to write to; was a POST cached?");
- }
-
- if (httpMinorVersion == 0) {
- sendChunked = false;
- }
-
- int fixedContentLength = policy.getFixedContentLength();
- if (requestBodyOut != null) {
- // request body was already initialized by the predecessor HTTP engine
- } else if (fixedContentLength != -1) {
- writeRequestHeaders(fixedContentLength);
- requestBodyOut = new FixedLengthOutputStream(requestOut, fixedContentLength);
- } else if (sendChunked) {
- writeRequestHeaders(-1);
- requestBodyOut = new ChunkedOutputStream(requestOut, chunkLength);
- } else if (requestHeaders.getContentLength() != -1) {
- writeRequestHeaders(requestHeaders.getContentLength());
- requestBodyOut = new RetryableOutputStream(requestHeaders.getContentLength());
- } else {
- requestBodyOut = new RetryableOutputStream();
- }
- }
-
- /**
- * @param body the response body, or null if it doesn't exist or isn't
- * available.
- */
- private void setResponse(ResponseHeaders headers, InputStream body) throws IOException {
- if (this.responseBodyIn != null) {
- throw new IllegalStateException();
- }
- this.responseHeaders = headers;
- this.httpMinorVersion = responseHeaders.getHeaders().getHttpMinorVersion();
- if (body != null) {
- initContentStream(body);
- }
- }
-
- private boolean hasRequestBody() {
- return method == POST || method == PUT;
- }
-
- /**
- * Returns the request body or null if this request doesn't have a body.
- */
- public final OutputStream getRequestBody() {
- if (responseSource == null) {
- throw new IllegalStateException();
- }
- return requestBodyOut;
- }
-
- public final boolean hasResponse() {
- return responseHeaders != null;
- }
-
- public final RequestHeaders getRequestHeaders() {
- return requestHeaders;
- }
-
- public final ResponseHeaders getResponseHeaders() {
- if (responseHeaders == null) {
- throw new IllegalStateException();
- }
- return responseHeaders;
- }
-
- public final int getResponseCode() {
- if (responseHeaders == null) {
- throw new IllegalStateException();
- }
- return responseHeaders.getHeaders().getResponseCode();
- }
-
- public final InputStream getResponseBody() {
- if (responseHeaders == null) {
- throw new IllegalStateException();
- }
- return responseBodyIn;
- }
-
- public final CacheResponse getCacheResponse() {
- return cacheResponse;
- }
-
- public final HttpConnection getConnection() {
- return connection;
- }
-
- public final boolean hasRecycledConnection() {
- return connection != null && connection.isRecycled();
- }
-
- /**
- * Returns true if {@code cacheResponse} is of the right type. This
- * condition is necessary but not sufficient for the cached response to
- * be used.
- */
- protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
- return true;
- }
-
- private void maybeCache() throws IOException {
- // Never cache responses to proxy CONNECT requests.
- if (method == CONNECT) {
- return;
- }
-
- // Are we caching at all?
- if (!policy.getUseCaches() || responseCache == null) {
- return;
- }
-
- // Should we cache this response for this request?
- if (!responseHeaders.isCacheable(requestHeaders)) {
- return;
- }
-
- // Offer this request to the cache.
- cacheRequest = responseCache.put(uri, getHttpConnectionToCache());
- }
-
- protected HttpURLConnection getHttpConnectionToCache() {
- return policy;
- }
-
- /**
- * Cause the socket connection to be released to the connection pool when
- * it is no longer needed. If it is already unneeded, it will be pooled
- * immediately.
- */
- public final void automaticallyReleaseConnectionToPool() {
- automaticallyReleaseConnectionToPool = true;
- if (connection != null && connectionReleased) {
- HttpConnectionPool.INSTANCE.recycle(connection);
- connection = null;
- }
- }
-
- public final void markConnectionAsRecycled() {
- if (connection != null) {
- connection.setRecycled();
- }
- }
-
- /**
- * Releases this engine so that its resources may be either reused or
- * closed.
- */
- public final void release(boolean reusable) {
- // If the response body comes from the cache, close it.
- if (responseBodyIn == cachedResponseBody) {
- IoUtils.closeQuietly(responseBodyIn);
- }
-
- if (!connectionReleased && connection != null) {
- connectionReleased = true;
-
- // We cannot reuse sockets that have incomplete output.
- if (requestBodyOut != null && !requestBodyOut.closed) {
- reusable = false;
- }
-
- // If the request specified that the connection shouldn't be reused,
- // don't reuse it. This advice doesn't apply to CONNECT requests because
- // the "Connection: close" header goes the origin server, not the proxy.
- if (requestHeaders.hasConnectionClose() && method != CONNECT) {
- reusable = false;
- }
-
- // If the response specified that the connection shouldn't be reused, don't reuse it.
- if (responseHeaders != null && responseHeaders.hasConnectionClose()) {
- reusable = false;
- }
-
- if (responseBodyIn instanceof UnknownLengthHttpInputStream) {
- reusable = false;
- }
-
- if (reusable && responseBodyIn != null) {
- // We must discard the response body before the connection can be reused.
- try {
- Streams.skipAll(responseBodyIn);
- } catch (IOException e) {
- reusable = false;
- }
- }
-
- if (!reusable) {
- connection.closeSocketAndStreams();
- connection = null;
- } else if (automaticallyReleaseConnectionToPool) {
- HttpConnectionPool.INSTANCE.recycle(connection);
- connection = null;
- }
- }
- }
-
- private void initContentStream(InputStream transferStream) throws IOException {
- if (transparentGzip && responseHeaders.isContentEncodingGzip()) {
- /*
- * If the response was transparently gzipped, remove the gzip header field
- * so clients don't double decompress. http://b/3009828
- *
- * Also remove the Content-Length in this case because it contains the length
- * of the gzipped response. This isn't terribly useful and is dangerous because
- * clients can query the content length, but not the content encoding.
- */
- responseHeaders.stripContentEncoding();
- responseHeaders.stripContentLength();
- responseBodyIn = new GZIPInputStream(transferStream);
- } else {
- responseBodyIn = transferStream;
- }
- }
-
- private InputStream getTransferStream() throws IOException {
- if (!hasResponseBody()) {
- return new FixedLengthInputStream(socketIn, cacheRequest, this, 0);
- }
-
- if (responseHeaders.isChunked()) {
- return new ChunkedInputStream(socketIn, cacheRequest, this);
- }
-
- if (responseHeaders.getContentLength() != -1) {
- return new FixedLengthInputStream(socketIn, cacheRequest, this,
- responseHeaders.getContentLength());
- }
-
- /*
- * Wrap the input stream from the HttpConnection (rather than
- * just returning "socketIn" directly here), so that we can control
- * its use after the reference escapes.
- */
- return new UnknownLengthHttpInputStream(socketIn, cacheRequest, this);
- }
-
- private void readResponseHeaders() throws IOException {
- RawHeaders headers;
- do {
- headers = new RawHeaders();
- headers.setStatusLine(Streams.readAsciiLine(socketIn));
- readHeaders(headers);
- } while (headers.getResponseCode() == HTTP_CONTINUE);
- setResponse(new ResponseHeaders(uri, headers), null);
- }
-
- /**
- * Returns true if the response must have a (possibly 0-length) body.
- * See RFC 2616 section 4.3.
- */
- public final boolean hasResponseBody() {
- int responseCode = responseHeaders.getHeaders().getResponseCode();
-
- // HEAD requests never yield a body regardless of the response headers.
- if (method == HEAD) {
- return false;
- }
-
- if (method != CONNECT
- && (responseCode < HTTP_CONTINUE || responseCode >= 200)
- && responseCode != HttpURLConnectionImpl.HTTP_NO_CONTENT
- && responseCode != HttpURLConnectionImpl.HTTP_NOT_MODIFIED) {
- return true;
- }
-
- /*
- * If the Content-Length or Transfer-Encoding headers disagree with the
- * response code, the response is malformed. For best compatibility, we
- * honor the headers.
- */
- if (responseHeaders.getContentLength() != -1 || responseHeaders.isChunked()) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Trailers are headers included after the last chunk of a response encoded
- * with chunked encoding.
- */
- final void readTrailers() throws IOException {
- readHeaders(responseHeaders.getHeaders());
- }
-
- private void readHeaders(RawHeaders headers) throws IOException {
- // parse the result headers until the first blank line
- String line;
- while (!(line = Streams.readAsciiLine(socketIn)).isEmpty()) {
- headers.addLine(line);
- }
-
- CookieHandler cookieHandler = CookieHandler.getDefault();
- if (cookieHandler != null) {
- cookieHandler.put(uri, headers.toMultimap());
- }
- }
-
- /**
- * Prepares the HTTP headers and sends them to the server.
- *
- * <p>For streaming requests with a body, headers must be prepared
- * <strong>before</strong> the output stream has been written to. Otherwise
- * the body would need to be buffered!
- *
- * <p>For non-streaming requests with a body, headers must be prepared
- * <strong>after</strong> the output stream has been written to and closed.
- * This ensures that the {@code Content-Length} header field receives the
- * proper value.
- *
- * @param contentLength the number of bytes in the request body, or -1 if
- * the request body length is unknown.
- */
- private void writeRequestHeaders(int contentLength) throws IOException {
- if (sentRequestMillis != -1) {
- throw new IllegalStateException();
- }
-
- RawHeaders headersToSend = getNetworkRequestHeaders();
- byte[] bytes = headersToSend.toHeaderString().getBytes(Charsets.ISO_8859_1);
-
- if (contentLength != -1 && bytes.length + contentLength <= MAX_REQUEST_BUFFER_LENGTH) {
- requestOut = new BufferedOutputStream(socketOut, bytes.length + contentLength);
- }
-
- sentRequestMillis = System.currentTimeMillis();
- requestOut.write(bytes);
- }
-
- /**
- * Returns the headers to send on a network request.
- *
- * <p>This adds the content length and content-type headers, which are
- * neither needed nor known when querying the response cache.
- *
- * <p>It updates the status line, which may need to be fully qualified if
- * the connection is using a proxy.
- */
- protected RawHeaders getNetworkRequestHeaders() throws IOException {
- requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
- int fixedContentLength = policy.getFixedContentLength();
- if (fixedContentLength != -1) {
- requestHeaders.setContentLength(fixedContentLength);
- } else if (sendChunked) {
- requestHeaders.setChunked();
- } else if (requestBodyOut instanceof RetryableOutputStream) {
- int contentLength = ((RetryableOutputStream) requestBodyOut).contentLength();
- requestHeaders.setContentLength(contentLength);
- }
-
- return requestHeaders.getHeaders();
- }
-
- /**
- * Populates requestHeaders with defaults and cookies.
- *
- * <p>This client doesn't specify a default {@code Accept} header because it
- * doesn't know what content types the application is interested in.
- */
- private void prepareRawRequestHeaders() throws IOException {
- requestHeaders.getHeaders().setStatusLine(getRequestLine());
-
- if (requestHeaders.getUserAgent() == null) {
- requestHeaders.setUserAgent(getDefaultUserAgent());
- }
-
- if (requestHeaders.getHost() == null) {
- requestHeaders.setHost(getOriginAddress(policy.getURL()));
- }
-
- if (httpMinorVersion > 0 && requestHeaders.getConnection() == null) {
- requestHeaders.setConnection("Keep-Alive");
- }
-
- if (requestHeaders.getAcceptEncoding() == null) {
- transparentGzip = true;
- requestHeaders.setAcceptEncoding("gzip");
- }
-
- if (hasRequestBody() && requestHeaders.getContentType() == null) {
- requestHeaders.setContentType("application/x-www-form-urlencoded");
- }
-
- long ifModifiedSince = policy.getIfModifiedSince();
- if (ifModifiedSince != 0) {
- requestHeaders.setIfModifiedSince(new Date(ifModifiedSince));
- }
-
- CookieHandler cookieHandler = CookieHandler.getDefault();
- if (cookieHandler != null) {
- requestHeaders.addCookies(
- cookieHandler.get(uri, requestHeaders.getHeaders().toMultimap()));
- }
- }
-
- private String getRequestLine() {
- String protocol = (httpMinorVersion == 0) ? "HTTP/1.0" : "HTTP/1.1";
- return method + " " + requestString() + " " + protocol;
- }
-
- private String requestString() {
- URL url = policy.getURL();
- if (includeAuthorityInRequestLine()) {
- return url.toString();
- } else {
- String fileOnly = url.getFile();
- if (fileOnly == null) {
- fileOnly = "/";
- } else if (!fileOnly.startsWith("/")) {
- fileOnly = "/" + fileOnly;
- }
- return fileOnly;
- }
- }
-
- /**
- * Returns true if the request line should contain the full URL with host
- * and port (like "GET http://android.com/foo HTTP/1.1") or only the path
- * (like "GET /foo HTTP/1.1").
- *
- * <p>This is non-final because for HTTPS it's never necessary to supply the
- * full URL, even if a proxy is in use.
- */
- protected boolean includeAuthorityInRequestLine() {
- return policy.usingProxy();
- }
-
- /**
- * Returns the SSL configuration for connections created by this engine.
- * We cannot reuse HTTPS connections if the socket factory has changed.
- */
- protected SSLSocketFactory getSslSocketFactory() {
- return null;
- }
-
- protected final String getDefaultUserAgent() {
- String agent = System.getProperty("http.agent");
- return agent != null ? agent : ("Java" + System.getProperty("java.version"));
- }
-
- protected final String getOriginAddress(URL url) {
- int port = url.getPort();
- String result = url.getHost();
- if (port > 0 && port != policy.getDefaultPort()) {
- result = result + ":" + port;
- }
- return result;
- }
-
- protected boolean requiresTunnel() {
- return false;
- }
-
- /**
- * Flushes the remaining request header and body, parses the HTTP response
- * headers and starts reading the HTTP response body if it exists.
- */
- public final void readResponse() throws IOException {
- if (hasResponse()) {
- return;
- }
-
- if (responseSource == null) {
- throw new IllegalStateException("readResponse() without sendRequest()");
- }
-
- if (!responseSource.requiresConnection()) {
- return;
- }
-
- if (sentRequestMillis == -1) {
- int contentLength = requestBodyOut instanceof RetryableOutputStream
- ? ((RetryableOutputStream) requestBodyOut).contentLength()
- : -1;
- writeRequestHeaders(contentLength);
- }
-
- if (requestBodyOut != null) {
- requestBodyOut.close();
- if (requestBodyOut instanceof RetryableOutputStream) {
- ((RetryableOutputStream) requestBodyOut).writeToSocket(requestOut);
- }
- }
-
- requestOut.flush();
- requestOut = socketOut;
-
- readResponseHeaders();
- responseHeaders.setLocalTimestamps(sentRequestMillis, System.currentTimeMillis());
-
- if (responseSource == ResponseSource.CONDITIONAL_CACHE) {
- if (cachedResponseHeaders.validate(responseHeaders)) {
- release(true);
- ResponseHeaders combinedHeaders = cachedResponseHeaders.combine(responseHeaders);
- setResponse(combinedHeaders, cachedResponseBody);
- if (responseCache instanceof ExtendedResponseCache) {
- ExtendedResponseCache httpResponseCache = (ExtendedResponseCache) responseCache;
- httpResponseCache.trackConditionalCacheHit();
- httpResponseCache.update(cacheResponse, getHttpConnectionToCache());
- }
- return;
- } else {
- IoUtils.closeQuietly(cachedResponseBody);
- }
- }
-
- if (hasResponseBody()) {
- maybeCache(); // reentrant. this calls into user code which may call back into this!
- }
-
- initContentStream(getTransferStream());
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpHandler.java b/luni/src/main/java/libcore/net/http/HttpHandler.java
deleted file mode 100644
index e168f42..0000000
--- a/luni/src/main/java/libcore/net/http/HttpHandler.java
+++ /dev/null
@@ -1,42 +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.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpHandler extends URLStreamHandler {
-
- @Override protected URLConnection openConnection(URL u) throws IOException {
- return new HttpURLConnectionImpl(u, getDefaultPort());
- }
-
- @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
- if (url == null || proxy == null) {
- throw new IllegalArgumentException("url == null || proxy == null");
- }
- return new HttpURLConnectionImpl(url, getDefaultPort(), proxy);
- }
-
- @Override protected int getDefaultPort() {
- return 80;
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpResponseCache.java b/luni/src/main/java/libcore/net/http/HttpResponseCache.java
deleted file mode 100644
index 1a9dfd1..0000000
--- a/luni/src/main/java/libcore/net/http/HttpResponseCache.java
+++ /dev/null
@@ -1,591 +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.net.http;
-
-import java.io.BufferedWriter;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FilterInputStream;
-import java.io.FilterOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.ExtendedResponseCache;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.ResponseSource;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URLConnection;
-import java.nio.charset.Charsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import libcore.io.Base64;
-import libcore.io.DiskLruCache;
-import libcore.io.IoUtils;
-import libcore.io.StrictLineReader;
-
-/**
- * Cache responses in a directory on the file system. Most clients should use
- * {@code android.net.HttpResponseCache}, the stable, documented front end for
- * this.
- */
-public final class HttpResponseCache extends ResponseCache implements ExtendedResponseCache {
- // TODO: add APIs to iterate the cache?
- private static final int VERSION = 201105;
- private static final int ENTRY_METADATA = 0;
- private static final int ENTRY_BODY = 1;
- private static final int ENTRY_COUNT = 2;
-
- private final DiskLruCache cache;
-
- /* read and write statistics, all guarded by 'this' */
- private int writeSuccessCount;
- private int writeAbortCount;
- private int networkCount;
- private int hitCount;
- private int requestCount;
-
- public HttpResponseCache(File directory, long maxSize) throws IOException {
- cache = DiskLruCache.open(directory, VERSION, ENTRY_COUNT, maxSize);
- }
-
- private String uriToKey(URI uri) {
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("MD5");
- byte[] md5bytes = messageDigest.digest(uri.toString().getBytes(Charsets.UTF_8));
- return IntegralToString.bytesToHexString(md5bytes, false);
- } catch (NoSuchAlgorithmException e) {
- throw new AssertionError(e);
- }
- }
-
- @Override public CacheResponse get(URI uri, String requestMethod,
- Map<String, List<String>> requestHeaders) {
- String key = uriToKey(uri);
- DiskLruCache.Snapshot snapshot;
- Entry entry;
- try {
- snapshot = cache.get(key);
- if (snapshot == null) {
- return null;
- }
- entry = new Entry(snapshot.getInputStream(ENTRY_METADATA));
- } catch (IOException e) {
- // Give up because the cache cannot be read.
- return null;
- }
-
- if (!entry.matches(uri, requestMethod, requestHeaders)) {
- snapshot.close();
- return null;
- }
-
- return entry.isHttps()
- ? new EntrySecureCacheResponse(entry, snapshot)
- : new EntryCacheResponse(entry, snapshot);
- }
-
- @Override public CacheRequest put(URI uri, URLConnection urlConnection) throws IOException {
- if (!(urlConnection instanceof HttpURLConnection)) {
- return null;
- }
-
- HttpURLConnection httpConnection = (HttpURLConnection) urlConnection;
- String requestMethod = httpConnection.getRequestMethod();
- String key = uriToKey(uri);
-
- if (requestMethod.equals(HttpEngine.POST)
- || requestMethod.equals(HttpEngine.PUT)
- || requestMethod.equals(HttpEngine.DELETE)) {
- try {
- cache.remove(key);
- } catch (IOException ignored) {
- // The cache cannot be written.
- }
- return null;
- } else if (!requestMethod.equals(HttpEngine.GET)) {
- /*
- * Don't cache non-GET responses. We're technically allowed to cache
- * HEAD requests and some POST requests, but the complexity of doing
- * so is high and the benefit is low.
- */
- return null;
- }
-
- HttpEngine httpEngine = getHttpEngine(httpConnection);
- if (httpEngine == null) {
- // Don't cache unless the HTTP implementation is ours.
- return null;
- }
-
- ResponseHeaders response = httpEngine.getResponseHeaders();
- if (response.hasVaryAll()) {
- return null;
- }
-
- RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders().getAll(
- response.getVaryFields());
- Entry entry = new Entry(uri, varyHeaders, httpConnection);
- DiskLruCache.Editor editor = null;
- try {
- editor = cache.edit(key);
- if (editor == null) {
- return null;
- }
- entry.writeTo(editor);
- return new CacheRequestImpl(editor);
- } catch (IOException e) {
- abortQuietly(editor);
- return null;
- }
- }
-
- /**
- * Handles a conditional request hit by updating the stored cache response
- * with the headers from {@code httpConnection}. The cached response body is
- * not updated. If the stored response has changed since {@code
- * conditionalCacheHit} was returned, this does nothing.
- */
- public void update(CacheResponse conditionalCacheHit, HttpURLConnection httpConnection) {
- HttpEngine httpEngine = getHttpEngine(httpConnection);
- URI uri = httpEngine.getUri();
- ResponseHeaders response = httpEngine.getResponseHeaders();
- RawHeaders varyHeaders = httpEngine.getRequestHeaders().getHeaders()
- .getAll(response.getVaryFields());
- Entry entry = new Entry(uri, varyHeaders, httpConnection);
- DiskLruCache.Snapshot snapshot = (conditionalCacheHit instanceof EntryCacheResponse)
- ? ((EntryCacheResponse) conditionalCacheHit).snapshot
- : ((EntrySecureCacheResponse) conditionalCacheHit).snapshot;
- DiskLruCache.Editor editor = null;
- try {
- editor = snapshot.edit(); // returns null if snapshot is not current
- if (editor != null) {
- entry.writeTo(editor);
- editor.commit();
- }
- } catch (IOException e) {
- abortQuietly(editor);
- }
- }
-
- private void abortQuietly(DiskLruCache.Editor editor) {
- // Give up because the cache cannot be written.
- try {
- if (editor != null) {
- editor.abort();
- }
- } catch (IOException ignored) {
- }
- }
-
- private HttpEngine getHttpEngine(HttpURLConnection httpConnection) {
- if (httpConnection instanceof HttpURLConnectionImpl) {
- return ((HttpURLConnectionImpl) httpConnection).getHttpEngine();
- } else if (httpConnection instanceof HttpsURLConnectionImpl) {
- return ((HttpsURLConnectionImpl) httpConnection).getHttpEngine();
- } else {
- return null;
- }
- }
-
- public DiskLruCache getCache() {
- return cache;
- }
-
- public synchronized int getWriteAbortCount() {
- return writeAbortCount;
- }
-
- public synchronized int getWriteSuccessCount() {
- return writeSuccessCount;
- }
-
- public synchronized void trackResponse(ResponseSource source) {
- requestCount++;
-
- switch (source) {
- case CACHE:
- hitCount++;
- break;
- case CONDITIONAL_CACHE:
- case NETWORK:
- networkCount++;
- break;
- }
- }
-
- public synchronized void trackConditionalCacheHit() {
- hitCount++;
- }
-
- public synchronized int getNetworkCount() {
- return networkCount;
- }
-
- public synchronized int getHitCount() {
- return hitCount;
- }
-
- public synchronized int getRequestCount() {
- return requestCount;
- }
-
- private final class CacheRequestImpl extends CacheRequest {
- private final DiskLruCache.Editor editor;
- private OutputStream cacheOut;
- private boolean done;
- private OutputStream body;
-
- public CacheRequestImpl(final DiskLruCache.Editor editor) throws IOException {
- this.editor = editor;
- this.cacheOut = editor.newOutputStream(ENTRY_BODY);
- this.body = new FilterOutputStream(cacheOut) {
- @Override public void close() throws IOException {
- synchronized (HttpResponseCache.this) {
- if (done) {
- return;
- }
- done = true;
- writeSuccessCount++;
- }
- super.close();
- editor.commit();
- }
-
- @Override
- public void write(byte[] buffer, int offset, int length) throws IOException {
- // Since we don't override "write(int oneByte)", we can write directly to "out"
- // and avoid the inefficient implementation from the FilterOutputStream.
- out.write(buffer, offset, length);
- }
- };
- }
-
- @Override public void abort() {
- synchronized (HttpResponseCache.this) {
- if (done) {
- return;
- }
- done = true;
- writeAbortCount++;
- }
- IoUtils.closeQuietly(cacheOut);
- try {
- editor.abort();
- } catch (IOException ignored) {
- }
- }
-
- @Override public OutputStream getBody() throws IOException {
- return body;
- }
- }
-
- private static final class Entry {
- private final String uri;
- private final RawHeaders varyHeaders;
- private final String requestMethod;
- private final RawHeaders responseHeaders;
- private final String cipherSuite;
- private final Certificate[] peerCertificates;
- private final Certificate[] localCertificates;
-
- /*
- * Reads an entry from an input stream. A typical entry looks like this:
- * http://google.com/foo
- * GET
- * 2
- * Accept-Language: fr-CA
- * Accept-Charset: UTF-8
- * HTTP/1.1 200 OK
- * 3
- * Content-Type: image/png
- * Content-Length: 100
- * Cache-Control: max-age=600
- *
- * A typical HTTPS file looks like this:
- * https://google.com/foo
- * GET
- * 2
- * Accept-Language: fr-CA
- * Accept-Charset: UTF-8
- * HTTP/1.1 200 OK
- * 3
- * Content-Type: image/png
- * Content-Length: 100
- * Cache-Control: max-age=600
- *
- * AES_256_WITH_MD5
- * 2
- * base64-encoded peerCertificate[0]
- * base64-encoded peerCertificate[1]
- * -1
- *
- * The file is newline separated. The first two lines are the URL and
- * the request method. Next is the number of HTTP Vary request header
- * lines, followed by those lines.
- *
- * Next is the response status line, followed by the number of HTTP
- * response header lines, followed by those lines.
- *
- * HTTPS responses also contain SSL session information. This begins
- * with a blank line, and then a line containing the cipher suite. Next
- * is the length of the peer certificate chain. These certificates are
- * base64-encoded and appear each on their own line. The next line
- * contains the length of the local certificate chain. These
- * certificates are also base64-encoded and appear each on their own
- * line. A length of -1 is used to encode a null array.
- */
- public Entry(InputStream in) throws IOException {
- try {
- StrictLineReader reader = new StrictLineReader(in, Charsets.US_ASCII);
- uri = reader.readLine();
- requestMethod = reader.readLine();
- varyHeaders = new RawHeaders();
- int varyRequestHeaderLineCount = reader.readInt();
- for (int i = 0; i < varyRequestHeaderLineCount; i++) {
- varyHeaders.addLine(reader.readLine());
- }
-
- responseHeaders = new RawHeaders();
- responseHeaders.setStatusLine(reader.readLine());
- int responseHeaderLineCount = reader.readInt();
- for (int i = 0; i < responseHeaderLineCount; i++) {
- responseHeaders.addLine(reader.readLine());
- }
-
- if (isHttps()) {
- String blank = reader.readLine();
- if (!blank.isEmpty()) {
- throw new IOException("expected \"\" but was \"" + blank + "\"");
- }
- cipherSuite = reader.readLine();
- peerCertificates = readCertArray(reader);
- localCertificates = readCertArray(reader);
- } else {
- cipherSuite = null;
- peerCertificates = null;
- localCertificates = null;
- }
- } finally {
- in.close();
- }
- }
-
- public Entry(URI uri, RawHeaders varyHeaders, HttpURLConnection httpConnection) {
- this.uri = uri.toString();
- this.varyHeaders = varyHeaders;
- this.requestMethod = httpConnection.getRequestMethod();
- this.responseHeaders = RawHeaders.fromMultimap(httpConnection.getHeaderFields());
-
- if (isHttps()) {
- HttpsURLConnection httpsConnection = (HttpsURLConnection) httpConnection;
- cipherSuite = httpsConnection.getCipherSuite();
- Certificate[] peerCertificatesNonFinal = null;
- try {
- peerCertificatesNonFinal = httpsConnection.getServerCertificates();
- } catch (SSLPeerUnverifiedException ignored) {
- }
- peerCertificates = peerCertificatesNonFinal;
- localCertificates = httpsConnection.getLocalCertificates();
- } else {
- cipherSuite = null;
- peerCertificates = null;
- localCertificates = null;
- }
- }
-
- public void writeTo(DiskLruCache.Editor editor) throws IOException {
- OutputStream out = editor.newOutputStream(ENTRY_METADATA);
- Writer writer = new BufferedWriter(new OutputStreamWriter(out, Charsets.UTF_8));
-
- writer.write(uri + '\n');
- writer.write(requestMethod + '\n');
- writer.write(Integer.toString(varyHeaders.length()) + '\n');
- for (int i = 0; i < varyHeaders.length(); i++) {
- writer.write(varyHeaders.getFieldName(i) + ": "
- + varyHeaders.getValue(i) + '\n');
- }
-
- writer.write(responseHeaders.getStatusLine() + '\n');
- writer.write(Integer.toString(responseHeaders.length()) + '\n');
- for (int i = 0; i < responseHeaders.length(); i++) {
- writer.write(responseHeaders.getFieldName(i) + ": "
- + responseHeaders.getValue(i) + '\n');
- }
-
- if (isHttps()) {
- writer.write('\n');
- writer.write(cipherSuite + '\n');
- writeCertArray(writer, peerCertificates);
- writeCertArray(writer, localCertificates);
- }
- writer.close();
- }
-
- private boolean isHttps() {
- return uri.startsWith("https://");
- }
-
- private Certificate[] readCertArray(StrictLineReader reader) throws IOException {
- int length = reader.readInt();
- if (length == -1) {
- return null;
- }
- try {
- CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
- Certificate[] result = new Certificate[length];
- for (int i = 0; i < result.length; i++) {
- String line = reader.readLine();
- byte[] bytes = Base64.decode(line.getBytes(Charsets.US_ASCII));
- result[i] = certificateFactory.generateCertificate(
- new ByteArrayInputStream(bytes));
- }
- return result;
- } catch (CertificateException e) {
- throw new IOException(e);
- }
- }
-
- private void writeCertArray(Writer writer, Certificate[] certificates) throws IOException {
- if (certificates == null) {
- writer.write("-1\n");
- return;
- }
- try {
- writer.write(Integer.toString(certificates.length) + '\n');
- for (Certificate certificate : certificates) {
- byte[] bytes = certificate.getEncoded();
- String line = Base64.encode(bytes);
- writer.write(line + '\n');
- }
- } catch (CertificateEncodingException e) {
- throw new IOException(e);
- }
- }
-
- public boolean matches(URI uri, String requestMethod,
- Map<String, List<String>> requestHeaders) {
- return this.uri.equals(uri.toString())
- && this.requestMethod.equals(requestMethod)
- && new ResponseHeaders(uri, responseHeaders)
- .varyMatches(varyHeaders.toMultimap(), requestHeaders);
- }
- }
-
- /**
- * Returns an input stream that reads the body of a snapshot, closing the
- * snapshot when the stream is closed.
- */
- private static InputStream newBodyInputStream(final DiskLruCache.Snapshot snapshot) {
- return new FilterInputStream(snapshot.getInputStream(ENTRY_BODY)) {
- @Override public void close() throws IOException {
- snapshot.close();
- super.close();
- }
- };
- }
-
- static class EntryCacheResponse extends CacheResponse {
- private final Entry entry;
- private final DiskLruCache.Snapshot snapshot;
- private final InputStream in;
-
- public EntryCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
- this.entry = entry;
- this.snapshot = snapshot;
- this.in = newBodyInputStream(snapshot);
- }
-
- @Override public Map<String, List<String>> getHeaders() {
- return entry.responseHeaders.toMultimap();
- }
-
- @Override public InputStream getBody() {
- return in;
- }
- }
-
- static class EntrySecureCacheResponse extends SecureCacheResponse {
- private final Entry entry;
- private final DiskLruCache.Snapshot snapshot;
- private final InputStream in;
-
- public EntrySecureCacheResponse(Entry entry, DiskLruCache.Snapshot snapshot) {
- this.entry = entry;
- this.snapshot = snapshot;
- this.in = newBodyInputStream(snapshot);
- }
-
- @Override public Map<String, List<String>> getHeaders() {
- return entry.responseHeaders.toMultimap();
- }
-
- @Override public InputStream getBody() {
- return in;
- }
-
- @Override public String getCipherSuite() {
- return entry.cipherSuite;
- }
-
- @Override public List<Certificate> getServerCertificateChain()
- throws SSLPeerUnverifiedException {
- if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
- throw new SSLPeerUnverifiedException(null);
- }
- return Arrays.asList(entry.peerCertificates.clone());
- }
-
- @Override public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
- if (entry.peerCertificates == null || entry.peerCertificates.length == 0) {
- throw new SSLPeerUnverifiedException(null);
- }
- return ((X509Certificate) entry.peerCertificates[0]).getSubjectX500Principal();
- }
-
- @Override public List<Certificate> getLocalCertificateChain() {
- if (entry.localCertificates == null || entry.localCertificates.length == 0) {
- return null;
- }
- return Arrays.asList(entry.localCertificates.clone());
- }
-
- @Override public Principal getLocalPrincipal() {
- if (entry.localCertificates == null || entry.localCertificates.length == 0) {
- return null;
- }
- return ((X509Certificate) entry.localCertificates[0]).getSubjectX500Principal();
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
deleted file mode 100644
index 3e6503f..0000000
--- a/luni/src/main/java/libcore/net/http/HttpURLConnectionImpl.java
+++ /dev/null
@@ -1,519 +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.net.http;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Authenticator;
-import java.net.HttpRetryException;
-import java.net.HttpURLConnection;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SocketPermission;
-import java.net.URL;
-import java.nio.charset.Charsets;
-import java.security.Permission;
-import java.util.List;
-import java.util.Map;
-import libcore.io.Base64;
-import libcore.io.IoUtils;
-
-/**
- * This implementation uses HttpEngine to send requests and receive responses.
- * This class may use multiple HttpEngines to follow redirects, authentication
- * retries, etc. to retrieve the final response body.
- *
- * <h3>What does 'connected' mean?</h3>
- * This class inherits a {@code connected} field from the superclass. That field
- * is <strong>not</strong> used to indicate not whether this URLConnection is
- * currently connected. Instead, it indicates whether a connection has ever been
- * attempted. Once a connection has been attempted, certain properties (request
- * header fields, request method, etc.) are immutable. Test the {@code
- * connection} field on this class for null/non-null to determine of an instance
- * is currently connected to a server.
- */
-class HttpURLConnectionImpl extends HttpURLConnection {
-
- private final int defaultPort;
-
- private Proxy proxy;
-
- private final RawHeaders rawRequestHeaders = new RawHeaders();
-
- private int redirectionCount;
-
- protected IOException httpEngineFailure;
- protected HttpEngine httpEngine;
-
- protected HttpURLConnectionImpl(URL url, int port) {
- super(url);
- defaultPort = port;
- }
-
- protected HttpURLConnectionImpl(URL url, int port, Proxy proxy) {
- this(url, port);
- this.proxy = proxy;
- }
-
- @Override public final void connect() throws IOException {
- initHttpEngine();
- try {
- httpEngine.sendRequest();
- } catch (IOException e) {
- httpEngineFailure = e;
- throw e;
- }
- }
-
- @Override public final void disconnect() {
- // Calling disconnect() before a connection exists should have no effect.
- if (httpEngine != null) {
- // We close the response body here instead of in
- // HttpEngine.release because that is called when input
- // has been completely read from the underlying socket.
- // However the response body can be a GZIPInputStream that
- // still has unread data.
- if (httpEngine.hasResponse()) {
- IoUtils.closeQuietly(httpEngine.getResponseBody());
- }
- httpEngine.release(false);
- }
- }
-
- /**
- * Returns an input stream from the server in the case of error such as the
- * requested file (txt, htm, html) is not found on the remote server.
- */
- @Override public final InputStream getErrorStream() {
- try {
- HttpEngine response = getResponse();
- if (response.hasResponseBody()
- && response.getResponseCode() >= HTTP_BAD_REQUEST) {
- return response.getResponseBody();
- }
- return null;
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * Returns the value of the field at {@code position}. Returns null if there
- * are fewer than {@code position} headers.
- */
- @Override public final String getHeaderField(int position) {
- try {
- return getResponse().getResponseHeaders().getHeaders().getValue(position);
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * Returns the value of the field corresponding to the {@code fieldName}, or
- * null if there is no such field. If the field has multiple values, the
- * last value is returned.
- */
- @Override public final String getHeaderField(String fieldName) {
- try {
- RawHeaders rawHeaders = getResponse().getResponseHeaders().getHeaders();
- return fieldName == null
- ? rawHeaders.getStatusLine()
- : rawHeaders.get(fieldName);
- } catch (IOException e) {
- return null;
- }
- }
-
- @Override public final String getHeaderFieldKey(int position) {
- try {
- return getResponse().getResponseHeaders().getHeaders().getFieldName(position);
- } catch (IOException e) {
- return null;
- }
- }
-
- @Override public final Map<String, List<String>> getHeaderFields() {
- try {
- return getResponse().getResponseHeaders().getHeaders().toMultimap();
- } catch (IOException e) {
- return null;
- }
- }
-
- @Override public final Map<String, List<String>> getRequestProperties() {
- if (connected) {
- throw new IllegalStateException(
- "Cannot access request header fields after connection is set");
- }
- return rawRequestHeaders.toMultimap();
- }
-
- @Override public final InputStream getInputStream() throws IOException {
- if (!doInput) {
- throw new ProtocolException("This protocol does not support input");
- }
-
- HttpEngine response = getResponse();
-
- /*
- * if the requested file does not exist, throw an exception formerly the
- * Error page from the server was returned if the requested file was
- * text/html this has changed to return FileNotFoundException for all
- * file types
- */
- if (getResponseCode() >= HTTP_BAD_REQUEST) {
- throw new FileNotFoundException(url.toString());
- }
-
- InputStream result = response.getResponseBody();
- if (result == null) {
- throw new IOException("No response body exists; responseCode=" + getResponseCode());
- }
- return result;
- }
-
- @Override public final OutputStream getOutputStream() throws IOException {
- connect();
-
- OutputStream result = httpEngine.getRequestBody();
- if (result == null) {
- throw new ProtocolException("method does not support a request body: " + method);
- } else if (httpEngine.hasResponse()) {
- throw new ProtocolException("cannot write request body after response has been read");
- }
-
- return result;
- }
-
- @Override public final Permission getPermission() throws IOException {
- String connectToAddress = getConnectToHost() + ":" + getConnectToPort();
- return new SocketPermission(connectToAddress, "connect, resolve");
- }
-
- private String getConnectToHost() {
- return usingProxy()
- ? ((InetSocketAddress) proxy.address()).getHostName()
- : getURL().getHost();
- }
-
- private int getConnectToPort() {
- int hostPort = usingProxy()
- ? ((InetSocketAddress) proxy.address()).getPort()
- : getURL().getPort();
- return hostPort < 0 ? getDefaultPort() : hostPort;
- }
-
- @Override public final String getRequestProperty(String field) {
- if (field == null) {
- return null;
- }
- return rawRequestHeaders.get(field);
- }
-
- private void initHttpEngine() throws IOException {
- if (httpEngineFailure != null) {
- throw httpEngineFailure;
- } else if (httpEngine != null) {
- return;
- }
-
- connected = true;
- try {
- if (doOutput) {
- if (method == HttpEngine.GET) {
- // they are requesting a stream to write to. This implies a POST method
- method = HttpEngine.POST;
- } else if (method != HttpEngine.POST && method != HttpEngine.PUT) {
- // If the request method is neither POST nor PUT, then you're not writing
- throw new ProtocolException(method + " does not support writing");
- }
- }
- httpEngine = newHttpEngine(method, rawRequestHeaders, null, null);
- } catch (IOException e) {
- httpEngineFailure = e;
- throw e;
- }
- }
-
- /**
- * Create a new HTTP engine. This hook method is non-final so it can be
- * overridden by HttpsURLConnectionImpl.
- */
- protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
- HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
- return new HttpEngine(this, method, requestHeaders, connection, requestBody);
- }
-
- /**
- * Aggressively tries to get the final HTTP response, potentially making
- * many HTTP requests in the process in order to cope with redirects and
- * authentication.
- */
- private HttpEngine getResponse() throws IOException {
- initHttpEngine();
-
- if (httpEngine.hasResponse()) {
- return httpEngine;
- }
-
- while (true) {
- try {
- httpEngine.sendRequest();
- httpEngine.readResponse();
- } catch (IOException e) {
- /*
- * If the connection was recycled, its staleness may have caused
- * the failure. Silently retry with a different connection.
- */
- OutputStream requestBody = httpEngine.getRequestBody();
- if (httpEngine.hasRecycledConnection()
- && (requestBody == null || requestBody instanceof RetryableOutputStream)) {
- httpEngine.release(false);
- httpEngine = newHttpEngine(method, rawRequestHeaders, null,
- (RetryableOutputStream) requestBody);
- continue;
- }
- httpEngineFailure = e;
- throw e;
- }
-
- Retry retry = processResponseHeaders();
- if (retry == Retry.NONE) {
- httpEngine.automaticallyReleaseConnectionToPool();
- return httpEngine;
- }
-
- /*
- * The first request was insufficient. Prepare for another...
- */
- String retryMethod = method;
- OutputStream requestBody = httpEngine.getRequestBody();
-
- /*
- * Although RFC 2616 10.3.2 specifies that a HTTP_MOVED_PERM
- * redirect should keep the same method, Chrome, Firefox and the
- * RI all issue GETs when following any redirect.
- */
- int responseCode = getResponseCode();
- if (responseCode == HTTP_MULT_CHOICE || responseCode == HTTP_MOVED_PERM
- || responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_SEE_OTHER) {
- retryMethod = HttpEngine.GET;
- requestBody = null;
- }
-
- if (requestBody != null && !(requestBody instanceof RetryableOutputStream)) {
- throw new HttpRetryException("Cannot retry streamed HTTP body",
- httpEngine.getResponseCode());
- }
-
- if (retry == Retry.DIFFERENT_CONNECTION) {
- httpEngine.automaticallyReleaseConnectionToPool();
- } else {
- httpEngine.markConnectionAsRecycled();
- }
-
- httpEngine.release(true);
-
- httpEngine = newHttpEngine(retryMethod, rawRequestHeaders,
- httpEngine.getConnection(), (RetryableOutputStream) requestBody);
- }
- }
-
- HttpEngine getHttpEngine() {
- return httpEngine;
- }
-
- enum Retry {
- NONE,
- SAME_CONNECTION,
- DIFFERENT_CONNECTION
- }
-
- /**
- * Returns the retry action to take for the current response headers. The
- * headers, proxy and target URL or this connection may be adjusted to
- * prepare for a follow up request.
- */
- private Retry processResponseHeaders() throws IOException {
- switch (getResponseCode()) {
- case HTTP_PROXY_AUTH:
- if (!usingProxy()) {
- throw new IOException(
- "Received HTTP_PROXY_AUTH (407) code while not using proxy");
- }
- // fall-through
- case HTTP_UNAUTHORIZED:
- boolean credentialsFound = processAuthHeader(getResponseCode(),
- httpEngine.getResponseHeaders(), rawRequestHeaders);
- return credentialsFound ? Retry.SAME_CONNECTION : Retry.NONE;
-
- case HTTP_MULT_CHOICE:
- case HTTP_MOVED_PERM:
- case HTTP_MOVED_TEMP:
- case HTTP_SEE_OTHER:
- if (!getInstanceFollowRedirects()) {
- return Retry.NONE;
- }
- if (++redirectionCount > HttpEngine.MAX_REDIRECTS) {
- throw new ProtocolException("Too many redirects");
- }
- String location = getHeaderField("Location");
- if (location == null) {
- return Retry.NONE;
- }
- URL previousUrl = url;
- url = new URL(previousUrl, location);
- if (!previousUrl.getProtocol().equals(url.getProtocol())) {
- return Retry.NONE; // the scheme changed; don't retry.
- }
- if (previousUrl.getHost().equals(url.getHost())
- && previousUrl.getEffectivePort() == url.getEffectivePort()) {
- return Retry.SAME_CONNECTION;
- } else {
- return Retry.DIFFERENT_CONNECTION;
- }
-
- default:
- return Retry.NONE;
- }
- }
-
- /**
- * React to a failed authorization response by looking up new credentials.
- *
- * @return true if credentials have been added to successorRequestHeaders
- * and another request should be attempted.
- */
- final boolean processAuthHeader(int responseCode, ResponseHeaders response,
- RawHeaders successorRequestHeaders) throws IOException {
- if (responseCode != HTTP_PROXY_AUTH && responseCode != HTTP_UNAUTHORIZED) {
- throw new IllegalArgumentException("Bad response code: " + responseCode);
- }
-
- // keep asking for username/password until authorized
- String challengeHeader = responseCode == HTTP_PROXY_AUTH
- ? "Proxy-Authenticate"
- : "WWW-Authenticate";
- String credentials = getAuthorizationCredentials(response.getHeaders(), challengeHeader);
- if (credentials == null) {
- return false; // could not find credentials, end request cycle
- }
-
- // add authorization credentials, bypassing the already-connected check
- String fieldName = responseCode == HTTP_PROXY_AUTH
- ? "Proxy-Authorization"
- : "Authorization";
- successorRequestHeaders.set(fieldName, credentials);
- return true;
- }
-
- /**
- * Returns the authorization credentials on the base of provided challenge.
- */
- private String getAuthorizationCredentials(RawHeaders responseHeaders, String challengeHeader)
- throws IOException {
- List<Challenge> challenges = HeaderParser.parseChallenges(responseHeaders, challengeHeader);
- if (challenges.isEmpty()) {
- throw new IOException("No authentication challenges found");
- }
-
- for (Challenge challenge : challenges) {
- // use the global authenticator to get the password
- PasswordAuthentication auth = Authenticator.requestPasswordAuthentication(
- getConnectToInetAddress(), getConnectToPort(), url.getProtocol(),
- challenge.realm, challenge.scheme);
- if (auth == null) {
- continue;
- }
-
- // base64 encode the username and password
- String usernameAndPassword = auth.getUserName() + ":" + new String(auth.getPassword());
- byte[] bytes = usernameAndPassword.getBytes(Charsets.ISO_8859_1);
- String encoded = Base64.encode(bytes);
- return challenge.scheme + " " + encoded;
- }
-
- return null;
- }
-
- private InetAddress getConnectToInetAddress() throws IOException {
- return usingProxy()
- ? ((InetSocketAddress) proxy.address()).getAddress()
- : InetAddress.getByName(getURL().getHost());
- }
-
- final int getDefaultPort() {
- return defaultPort;
- }
-
- /** @see HttpURLConnection#setFixedLengthStreamingMode(int) */
- final int getFixedContentLength() {
- return fixedContentLength;
- }
-
- /** @see HttpURLConnection#setChunkedStreamingMode(int) */
- final int getChunkLength() {
- return chunkLength;
- }
-
- final Proxy getProxy() {
- return proxy;
- }
-
- final void setProxy(Proxy proxy) {
- this.proxy = proxy;
- }
-
- @Override public final boolean usingProxy() {
- return (proxy != null && proxy.type() != Proxy.Type.DIRECT);
- }
-
- @Override public String getResponseMessage() throws IOException {
- return getResponse().getResponseHeaders().getHeaders().getResponseMessage();
- }
-
- @Override public final int getResponseCode() throws IOException {
- return getResponse().getResponseCode();
- }
-
- @Override public final void setRequestProperty(String field, String newValue) {
- if (connected) {
- throw new IllegalStateException("Cannot set request property after connection is made");
- }
- if (field == null) {
- throw new NullPointerException("field == null");
- }
- rawRequestHeaders.set(field, newValue);
- }
-
- @Override public final void addRequestProperty(String field, String value) {
- if (connected) {
- throw new IllegalStateException("Cannot add request property after connection is made");
- }
- if (field == null) {
- throw new NullPointerException("field == null");
- }
- rawRequestHeaders.add(field, value);
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsHandler.java b/luni/src/main/java/libcore/net/http/HttpsHandler.java
deleted file mode 100644
index ed9ba72..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsHandler.java
+++ /dev/null
@@ -1,42 +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.net.http;
-
-import java.io.IOException;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-
-public final class HttpsHandler extends URLStreamHandler {
-
- @Override protected URLConnection openConnection(URL url) throws IOException {
- return new HttpsURLConnectionImpl(url, getDefaultPort());
- }
-
- @Override protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
- if (url == null || proxy == null) {
- throw new IllegalArgumentException("url == null || proxy == null");
- }
- return new HttpsURLConnectionImpl(url, getDefaultPort(), proxy);
- }
-
- @Override protected int getDefaultPort() {
- return 443;
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java b/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
deleted file mode 100644
index 9e3e4ef..0000000
--- a/luni/src/main/java/libcore/net/http/HttpsURLConnectionImpl.java
+++ /dev/null
@@ -1,580 +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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.CacheResponse;
-import java.net.HttpURLConnection;
-import java.net.ProtocolException;
-import java.net.Proxy;
-import java.net.SecureCacheResponse;
-import java.net.URL;
-import java.security.Permission;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.util.List;
-import java.util.Map;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLHandshakeException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-
-final class HttpsURLConnectionImpl extends HttpsURLConnection {
-
- /** HttpUrlConnectionDelegate allows reuse of HttpURLConnectionImpl */
- private final HttpUrlConnectionDelegate delegate;
-
- protected HttpsURLConnectionImpl(URL url, int port) {
- super(url);
- delegate = new HttpUrlConnectionDelegate(url, port);
- }
-
- protected HttpsURLConnectionImpl(URL url, int port, Proxy proxy) {
- super(url);
- delegate = new HttpUrlConnectionDelegate(url, port, proxy);
- }
-
- private void checkConnected() {
- if (delegate.getSSLSocket() == null) {
- throw new IllegalStateException("Connection has not yet been established");
- }
- }
-
- HttpEngine getHttpEngine() {
- return delegate.getHttpEngine();
- }
-
- @Override
- public String getCipherSuite() {
- SecureCacheResponse cacheResponse = delegate.getCacheResponse();
- if (cacheResponse != null) {
- return cacheResponse.getCipherSuite();
- }
- checkConnected();
- return delegate.getSSLSocket().getSession().getCipherSuite();
- }
-
- @Override
- public Certificate[] getLocalCertificates() {
- SecureCacheResponse cacheResponse = delegate.getCacheResponse();
- if (cacheResponse != null) {
- List<Certificate> result = cacheResponse.getLocalCertificateChain();
- return result != null ? result.toArray(new Certificate[result.size()]) : null;
- }
- checkConnected();
- return delegate.getSSLSocket().getSession().getLocalCertificates();
- }
-
- @Override
- public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException {
- SecureCacheResponse cacheResponse = delegate.getCacheResponse();
- if (cacheResponse != null) {
- List<Certificate> result = cacheResponse.getServerCertificateChain();
- return result != null ? result.toArray(new Certificate[result.size()]) : null;
- }
- checkConnected();
- return delegate.getSSLSocket().getSession().getPeerCertificates();
- }
-
- @Override
- public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
- SecureCacheResponse cacheResponse = delegate.getCacheResponse();
- if (cacheResponse != null) {
- return cacheResponse.getPeerPrincipal();
- }
- checkConnected();
- return delegate.getSSLSocket().getSession().getPeerPrincipal();
- }
-
- @Override
- public Principal getLocalPrincipal() {
- SecureCacheResponse cacheResponse = delegate.getCacheResponse();
- if (cacheResponse != null) {
- return cacheResponse.getLocalPrincipal();
- }
- checkConnected();
- return delegate.getSSLSocket().getSession().getLocalPrincipal();
- }
-
- @Override
- public void disconnect() {
- delegate.disconnect();
- }
-
- @Override
- public InputStream getErrorStream() {
- return delegate.getErrorStream();
- }
-
- @Override
- public String getRequestMethod() {
- return delegate.getRequestMethod();
- }
-
- @Override
- public int getResponseCode() throws IOException {
- return delegate.getResponseCode();
- }
-
- @Override
- public String getResponseMessage() throws IOException {
- return delegate.getResponseMessage();
- }
-
- @Override
- public void setRequestMethod(String method) throws ProtocolException {
- delegate.setRequestMethod(method);
- }
-
- @Override
- public boolean usingProxy() {
- return delegate.usingProxy();
- }
-
- @Override
- public boolean getInstanceFollowRedirects() {
- return delegate.getInstanceFollowRedirects();
- }
-
- @Override
- public void setInstanceFollowRedirects(boolean followRedirects) {
- delegate.setInstanceFollowRedirects(followRedirects);
- }
-
- @Override
- public void connect() throws IOException {
- connected = true;
- delegate.connect();
- }
-
- @Override
- public boolean getAllowUserInteraction() {
- return delegate.getAllowUserInteraction();
- }
-
- @Override
- public Object getContent() throws IOException {
- return delegate.getContent();
- }
-
- @SuppressWarnings("unchecked") // Spec does not generify
- @Override
- public Object getContent(Class[] types) throws IOException {
- return delegate.getContent(types);
- }
-
- @Override
- public String getContentEncoding() {
- return delegate.getContentEncoding();
- }
-
- @Override
- public int getContentLength() {
- return delegate.getContentLength();
- }
-
- @Override
- public String getContentType() {
- return delegate.getContentType();
- }
-
- @Override
- public long getDate() {
- return delegate.getDate();
- }
-
- @Override
- public boolean getDefaultUseCaches() {
- return delegate.getDefaultUseCaches();
- }
-
- @Override
- public boolean getDoInput() {
- return delegate.getDoInput();
- }
-
- @Override
- public boolean getDoOutput() {
- return delegate.getDoOutput();
- }
-
- @Override
- public long getExpiration() {
- return delegate.getExpiration();
- }
-
- @Override
- public String getHeaderField(int pos) {
- return delegate.getHeaderField(pos);
- }
-
- @Override
- public Map<String, List<String>> getHeaderFields() {
- return delegate.getHeaderFields();
- }
-
- @Override
- public Map<String, List<String>> getRequestProperties() {
- return delegate.getRequestProperties();
- }
-
- @Override
- public void addRequestProperty(String field, String newValue) {
- delegate.addRequestProperty(field, newValue);
- }
-
- @Override
- public String getHeaderField(String key) {
- return delegate.getHeaderField(key);
- }
-
- @Override
- public long getHeaderFieldDate(String field, long defaultValue) {
- return delegate.getHeaderFieldDate(field, defaultValue);
- }
-
- @Override
- public int getHeaderFieldInt(String field, int defaultValue) {
- return delegate.getHeaderFieldInt(field, defaultValue);
- }
-
- @Override
- public String getHeaderFieldKey(int posn) {
- return delegate.getHeaderFieldKey(posn);
- }
-
- @Override
- public long getIfModifiedSince() {
- return delegate.getIfModifiedSince();
- }
-
- @Override
- public InputStream getInputStream() throws IOException {
- return delegate.getInputStream();
- }
-
- @Override
- public long getLastModified() {
- return delegate.getLastModified();
- }
-
- @Override
- public OutputStream getOutputStream() throws IOException {
- return delegate.getOutputStream();
- }
-
- @Override
- public Permission getPermission() throws IOException {
- return delegate.getPermission();
- }
-
- @Override
- public String getRequestProperty(String field) {
- return delegate.getRequestProperty(field);
- }
-
- @Override
- public URL getURL() {
- return delegate.getURL();
- }
-
- @Override
- public boolean getUseCaches() {
- return delegate.getUseCaches();
- }
-
- @Override
- public void setAllowUserInteraction(boolean newValue) {
- delegate.setAllowUserInteraction(newValue);
- }
-
- @Override
- public void setDefaultUseCaches(boolean newValue) {
- delegate.setDefaultUseCaches(newValue);
- }
-
- @Override
- public void setDoInput(boolean newValue) {
- delegate.setDoInput(newValue);
- }
-
- @Override
- public void setDoOutput(boolean newValue) {
- delegate.setDoOutput(newValue);
- }
-
- @Override
- public void setIfModifiedSince(long newValue) {
- delegate.setIfModifiedSince(newValue);
- }
-
- @Override
- public void setRequestProperty(String field, String newValue) {
- delegate.setRequestProperty(field, newValue);
- }
-
- @Override
- public void setUseCaches(boolean newValue) {
- delegate.setUseCaches(newValue);
- }
-
- @Override
- public void setConnectTimeout(int timeoutMillis) {
- delegate.setConnectTimeout(timeoutMillis);
- }
-
- @Override
- public int getConnectTimeout() {
- return delegate.getConnectTimeout();
- }
-
- @Override
- public void setReadTimeout(int timeoutMillis) {
- delegate.setReadTimeout(timeoutMillis);
- }
-
- @Override
- public int getReadTimeout() {
- return delegate.getReadTimeout();
- }
-
- @Override
- public String toString() {
- return delegate.toString();
- }
-
- @Override
- public void setFixedLengthStreamingMode(int contentLength) {
- delegate.setFixedLengthStreamingMode(contentLength);
- }
-
- @Override
- public void setChunkedStreamingMode(int chunkLength) {
- delegate.setChunkedStreamingMode(chunkLength);
- }
-
- private final class HttpUrlConnectionDelegate extends HttpURLConnectionImpl {
- private HttpUrlConnectionDelegate(URL url, int port) {
- super(url, port);
- }
-
- private HttpUrlConnectionDelegate(URL url, int port, Proxy proxy) {
- super(url, port, proxy);
- }
-
- @Override protected HttpEngine newHttpEngine(String method, RawHeaders requestHeaders,
- HttpConnection connection, RetryableOutputStream requestBody) throws IOException {
- return new HttpsEngine(this, method, requestHeaders, connection, requestBody,
- HttpsURLConnectionImpl.this);
- }
-
- public SecureCacheResponse getCacheResponse() {
- HttpsEngine engine = (HttpsEngine) httpEngine;
- return engine != null ? (SecureCacheResponse) engine.getCacheResponse() : null;
- }
-
- public SSLSocket getSSLSocket() {
- HttpsEngine engine = (HttpsEngine) httpEngine;
- return engine != null ? engine.sslSocket : null;
- }
- }
-
- private static class HttpsEngine extends HttpEngine {
-
- /**
- * Local stash of HttpsEngine.connection.sslSocket for answering
- * queries such as getCipherSuite even after
- * httpsEngine.Connection has been recycled. It's presence is also
- * used to tell if the HttpsURLConnection is considered connected,
- * as opposed to the connected field of URLConnection or the a
- * non-null connect in HttpURLConnectionImpl
- */
- private SSLSocket sslSocket;
-
- private final HttpsURLConnectionImpl enclosing;
-
- /**
- * @param policy the HttpURLConnectionImpl with connection configuration
- * @param enclosing the HttpsURLConnection with HTTPS features
- */
- private HttpsEngine(HttpURLConnectionImpl policy, String method, RawHeaders requestHeaders,
- HttpConnection connection, RetryableOutputStream requestBody,
- HttpsURLConnectionImpl enclosing) throws IOException {
- super(policy, method, requestHeaders, connection, requestBody);
- this.sslSocket = connection != null ? connection.getSecureSocketIfConnected() : null;
- this.enclosing = enclosing;
- }
-
- @Override protected void connect() throws IOException {
- // first try an SSL connection with compression and
- // various TLS extensions enabled, if it fails (and its
- // not unheard of that it will) fallback to a more
- // barebones connections
- boolean connectionReused;
- try {
- connectionReused = makeSslConnection(true);
- } catch (IOException e) {
- // If the problem was a CertificateException from the X509TrustManager,
- // do not retry, we didn't have an abrupt server initiated exception.
- if (e instanceof SSLHandshakeException
- && e.getCause() instanceof CertificateException) {
- throw e;
- }
- release(false);
- connectionReused = makeSslConnection(false);
- }
-
- if (!connectionReused) {
- sslSocket = connection.verifySecureSocketHostname(enclosing.getHostnameVerifier());
- }
- }
-
- /**
- * Attempt to make an https connection. Returns true if a
- * connection was reused, false otherwise.
- *
- * @param tlsTolerant If true, assume server can handle common
- * TLS extensions and SSL deflate compression. If false, use
- * an SSL3 only fallback mode without compression.
- */
- private boolean makeSslConnection(boolean tlsTolerant) throws IOException {
- // make an SSL Tunnel on the first message pair of each SSL + proxy connection
- if (connection == null) {
- connection = openSocketConnection();
- if (connection.getAddress().getProxy() != null) {
- makeTunnel(policy, connection, getRequestHeaders());
- }
- }
-
- // if super.makeConnection returned a connection from the
- // pool, sslSocket needs to be initialized here. If it is
- // a new connection, it will be initialized by
- // getSecureSocket below.
- sslSocket = connection.getSecureSocketIfConnected();
-
- // we already have an SSL connection,
- if (sslSocket != null) {
- return true;
- }
-
- connection.setupSecureSocket(enclosing.getSSLSocketFactory(), tlsTolerant);
- return false;
- }
-
- /**
- * To make an HTTPS connection over an HTTP proxy, send an unencrypted
- * CONNECT request to create the proxy connection. This may need to be
- * retried if the proxy requires authorization.
- */
- private void makeTunnel(HttpURLConnectionImpl policy, HttpConnection connection,
- RequestHeaders requestHeaders) throws IOException {
- RawHeaders rawRequestHeaders = requestHeaders.getHeaders();
- while (true) {
- HttpEngine connect = new ProxyConnectEngine(policy, rawRequestHeaders, connection);
- connect.sendRequest();
- connect.readResponse();
-
- int responseCode = connect.getResponseCode();
- switch (connect.getResponseCode()) {
- case HTTP_OK:
- return;
- case HTTP_PROXY_AUTH:
- rawRequestHeaders = new RawHeaders(rawRequestHeaders);
- boolean credentialsFound = policy.processAuthHeader(HTTP_PROXY_AUTH,
- connect.getResponseHeaders(), rawRequestHeaders);
- if (credentialsFound) {
- continue;
- } else {
- throw new IOException("Failed to authenticate with proxy");
- }
- default:
- throw new IOException("Unexpected response code for CONNECT: " + responseCode);
- }
- }
- }
-
- @Override protected boolean acceptCacheResponseType(CacheResponse cacheResponse) {
- return cacheResponse instanceof SecureCacheResponse;
- }
-
- @Override protected boolean includeAuthorityInRequestLine() {
- // Even if there is a proxy, it isn't involved. Always request just the file.
- return false;
- }
-
- @Override protected SSLSocketFactory getSslSocketFactory() {
- return enclosing.getSSLSocketFactory();
- }
-
- @Override protected HttpURLConnection getHttpConnectionToCache() {
- return enclosing;
- }
- }
-
- private static class ProxyConnectEngine extends HttpEngine {
- public ProxyConnectEngine(HttpURLConnectionImpl policy, RawHeaders requestHeaders,
- HttpConnection connection) throws IOException {
- super(policy, HttpEngine.CONNECT, requestHeaders, connection, null);
- }
-
- /**
- * If we're establishing an HTTPS tunnel with CONNECT (RFC 2817 5.2), send
- * only the minimum set of headers. This avoids sending potentially
- * sensitive data like HTTP cookies to the proxy unencrypted.
- */
- @Override protected RawHeaders getNetworkRequestHeaders() throws IOException {
- RequestHeaders privateHeaders = getRequestHeaders();
- URL url = policy.getURL();
-
- RawHeaders result = new RawHeaders();
- result.setStatusLine("CONNECT " + url.getHost() + ":" + url.getEffectivePort()
- + " HTTP/1.1");
-
- // Always set Host and User-Agent.
- String host = privateHeaders.getHost();
- if (host == null) {
- host = getOriginAddress(url);
- }
- result.set("Host", host);
-
- String userAgent = privateHeaders.getUserAgent();
- if (userAgent == null) {
- userAgent = getDefaultUserAgent();
- }
- result.set("User-Agent", userAgent);
-
- // Copy over the Proxy-Authorization header if it exists.
- String proxyAuthorization = privateHeaders.getProxyAuthorization();
- if (proxyAuthorization != null) {
- result.set("Proxy-Authorization", proxyAuthorization);
- }
-
- // Always set the Proxy-Connection to Keep-Alive for the benefit of
- // HTTP/1.0 proxies like Squid.
- result.set("Proxy-Connection", "Keep-Alive");
- return result;
- }
-
- @Override protected boolean requiresTunnel() {
- return true;
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/RawHeaders.java b/luni/src/main/java/libcore/net/http/RawHeaders.java
deleted file mode 100644
index 21b48f1..0000000
--- a/luni/src/main/java/libcore/net/http/RawHeaders.java
+++ /dev/null
@@ -1,297 +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.net.http;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-/**
- * The HTTP status and unparsed header fields of a single HTTP message. Values
- * are represented as uninterpreted strings; use {@link RequestHeaders} and
- * {@link ResponseHeaders} for interpreted headers. This class maintains the
- * order of the header fields within the HTTP message.
- *
- * <p>This class tracks fields line-by-line. A field with multiple comma-
- * separated values on the same line will be treated as a field with a single
- * value by this class. It is the caller's responsibility to detect and split
- * on commas if their field permits multiple values. This simplifies use of
- * single-valued fields whose values routinely contain commas, such as cookies
- * or dates.
- *
- * <p>This class trims whitespace from values. It never returns values with
- * leading or trailing whitespace.
- */
-public final class RawHeaders {
- private static final Comparator<String> FIELD_NAME_COMPARATOR = new Comparator<String>() {
- @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
- @Override public int compare(String a, String b) {
- if (a == b) {
- return 0;
- } else if (a == null) {
- return -1;
- } else if (b == null) {
- return 1;
- } else {
- return String.CASE_INSENSITIVE_ORDER.compare(a, b);
- }
- }
- };
-
- private final List<String> namesAndValues = new ArrayList<String>(20);
- private String statusLine;
- private int httpMinorVersion = 1;
- private int responseCode = -1;
- private String responseMessage;
-
- public RawHeaders() {}
-
- public RawHeaders(RawHeaders copyFrom) {
- namesAndValues.addAll(copyFrom.namesAndValues);
- statusLine = copyFrom.statusLine;
- httpMinorVersion = copyFrom.httpMinorVersion;
- responseCode = copyFrom.responseCode;
- responseMessage = copyFrom.responseMessage;
- }
-
- /**
- * Sets the response status line (like "HTTP/1.0 200 OK") or request line
- * (like "GET / HTTP/1.1").
- */
- public void setStatusLine(String statusLine) {
- statusLine = statusLine.trim();
- this.statusLine = statusLine;
-
- if (statusLine == null || !statusLine.startsWith("HTTP/")) {
- return;
- }
- statusLine = statusLine.trim();
- int mark = statusLine.indexOf(" ") + 1;
- if (mark == 0) {
- return;
- }
- if (statusLine.charAt(mark - 2) != '1') {
- this.httpMinorVersion = 0;
- }
- int last = mark + 3;
- if (last > statusLine.length()) {
- last = statusLine.length();
- }
- this.responseCode = Integer.parseInt(statusLine.substring(mark, last));
- if (last + 1 <= statusLine.length()) {
- this.responseMessage = statusLine.substring(last + 1);
- }
- }
-
- public String getStatusLine() {
- return statusLine;
- }
-
- /**
- * Returns the status line's HTTP minor version. This returns 0 for HTTP/1.0
- * and 1 for HTTP/1.1. This returns 1 if the HTTP version is unknown.
- */
- public int getHttpMinorVersion() {
- return httpMinorVersion != -1 ? httpMinorVersion : 1;
- }
-
- /**
- * Returns the HTTP status code or -1 if it is unknown.
- */
- public int getResponseCode() {
- return responseCode;
- }
-
- /**
- * Returns the HTTP status message or null if it is unknown.
- */
- public String getResponseMessage() {
- return responseMessage;
- }
-
- /**
- * Add an HTTP header line containing a field name, a literal colon, and a
- * value.
- */
- public void addLine(String line) {
- int index = line.indexOf(":");
- if (index == -1) {
- add("", line);
- } else {
- add(line.substring(0, index), line.substring(index + 1));
- }
- }
-
- /**
- * Add a field with the specified value.
- */
- public void add(String fieldName, String value) {
- if (fieldName == null) {
- throw new IllegalArgumentException("fieldName == null");
- }
- if (value == null) {
- /*
- * Given null values, the RI sends a malformed field line like
- * "Accept\r\n". For platform compatibility and HTTP compliance, we
- * print a warning and ignore null values.
- */
- System.logW("Ignoring HTTP header field '" + fieldName + "' because its value is null");
- return;
- }
- namesAndValues.add(fieldName);
- namesAndValues.add(value.trim());
- }
-
- public void removeAll(String fieldName) {
- for (int i = 0; i < namesAndValues.size(); i += 2) {
- if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
- namesAndValues.remove(i); // field name
- namesAndValues.remove(i); // value
- }
- }
- }
-
- public void addAll(String fieldName, List<String> headerFields) {
- for (String value : headerFields) {
- add(fieldName, value);
- }
- }
-
- /**
- * Set a field with the specified value. If the field is not found, it is
- * added. If the field is found, the existing values are replaced.
- */
- public void set(String fieldName, String value) {
- removeAll(fieldName);
- add(fieldName, value);
- }
-
- /**
- * Returns the number of field values.
- */
- public int length() {
- return namesAndValues.size() / 2;
- }
-
- /**
- * Returns the field at {@code position} or null if that is out of range.
- */
- public String getFieldName(int index) {
- int fieldNameIndex = index * 2;
- if (fieldNameIndex < 0 || fieldNameIndex >= namesAndValues.size()) {
- return null;
- }
- return namesAndValues.get(fieldNameIndex);
- }
-
- /**
- * Returns the value at {@code index} or null if that is out of range.
- */
- public String getValue(int index) {
- int valueIndex = index * 2 + 1;
- if (valueIndex < 0 || valueIndex >= namesAndValues.size()) {
- return null;
- }
- return namesAndValues.get(valueIndex);
- }
-
- /**
- * Returns the last value corresponding to the specified field, or null.
- */
- public String get(String fieldName) {
- for (int i = namesAndValues.size() - 2; i >= 0; i -= 2) {
- if (fieldName.equalsIgnoreCase(namesAndValues.get(i))) {
- return namesAndValues.get(i + 1);
- }
- }
- return null;
- }
-
- /**
- * @param fieldNames a case-insensitive set of HTTP header field names.
- */
- public RawHeaders getAll(Set<String> fieldNames) {
- RawHeaders result = new RawHeaders();
- for (int i = 0; i < namesAndValues.size(); i += 2) {
- String fieldName = namesAndValues.get(i);
- if (fieldNames.contains(fieldName)) {
- result.add(fieldName, namesAndValues.get(i + 1));
- }
- }
- return result;
- }
-
- public String toHeaderString() {
- StringBuilder result = new StringBuilder(256);
- result.append(statusLine).append("\r\n");
- for (int i = 0; i < namesAndValues.size(); i += 2) {
- result.append(namesAndValues.get(i)).append(": ")
- .append(namesAndValues.get(i + 1)).append("\r\n");
- }
- result.append("\r\n");
- return result.toString();
- }
-
- /**
- * Returns an immutable map containing each field to its list of values. The
- * status line is mapped to null.
- */
- public Map<String, List<String>> toMultimap() {
- Map<String, List<String>> result = new TreeMap<String, List<String>>(FIELD_NAME_COMPARATOR);
- for (int i = 0; i < namesAndValues.size(); i += 2) {
- String fieldName = namesAndValues.get(i);
- String value = namesAndValues.get(i + 1);
-
- List<String> allValues = new ArrayList<String>();
- List<String> otherValues = result.get(fieldName);
- if (otherValues != null) {
- allValues.addAll(otherValues);
- }
- allValues.add(value);
- result.put(fieldName, Collections.unmodifiableList(allValues));
- }
- if (statusLine != null) {
- result.put(null, Collections.unmodifiableList(Collections.singletonList(statusLine)));
- }
- return Collections.unmodifiableMap(result);
- }
-
- /**
- * Creates a new instance from the given map of fields to values. If
- * present, the null field's last element will be used to set the status
- * line.
- */
- public static RawHeaders fromMultimap(Map<String, List<String>> map) {
- RawHeaders result = new RawHeaders();
- for (Entry<String, List<String>> entry : map.entrySet()) {
- String fieldName = entry.getKey();
- List<String> values = entry.getValue();
- if (fieldName != null) {
- result.addAll(fieldName, values);
- } else if (!values.isEmpty()) {
- result.setStatusLine(values.get(values.size() - 1));
- }
- }
- return result;
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/RequestHeaders.java b/luni/src/main/java/libcore/net/http/RequestHeaders.java
deleted file mode 100644
index 3b536ce..0000000
--- a/luni/src/main/java/libcore/net/http/RequestHeaders.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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 libcore.net.http;
-
-import java.net.URI;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Parsed HTTP request headers.
- */
-public final class RequestHeaders {
- private final URI uri;
- private final RawHeaders headers;
-
- /** Don't use a cache to satisfy this request. */
- private boolean noCache;
- private int maxAgeSeconds = -1;
- private int maxStaleSeconds = -1;
- private int minFreshSeconds = -1;
-
- /**
- * This field's name "only-if-cached" is misleading. It actually means "do
- * not use the network". It is set by a client who only wants to make a
- * request if it can be fully satisfied by the cache. Cached responses that
- * would require validation (ie. conditional gets) are not permitted if this
- * header is set.
- */
- private boolean onlyIfCached;
-
- /**
- * True if the request contains an authorization field. Although this isn't
- * necessarily a shared cache, it follows the spec's strict requirements for
- * shared caches.
- */
- private boolean hasAuthorization;
-
- private int contentLength = -1;
- private String transferEncoding;
- private String userAgent;
- private String host;
- private String connection;
- private String acceptEncoding;
- private String contentType;
- private String ifModifiedSince;
- private String ifNoneMatch;
- private String proxyAuthorization;
-
- public RequestHeaders(URI uri, RawHeaders headers) {
- this.uri = uri;
- this.headers = headers;
-
- HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
- @Override public void handle(String directive, String parameter) {
- if (directive.equalsIgnoreCase("no-cache")) {
- noCache = true;
- } else if (directive.equalsIgnoreCase("max-age")) {
- maxAgeSeconds = HeaderParser.parseSeconds(parameter);
- } else if (directive.equalsIgnoreCase("max-stale")) {
- maxStaleSeconds = HeaderParser.parseSeconds(parameter);
- } else if (directive.equalsIgnoreCase("min-fresh")) {
- minFreshSeconds = HeaderParser.parseSeconds(parameter);
- } else if (directive.equalsIgnoreCase("only-if-cached")) {
- onlyIfCached = true;
- }
- }
- };
-
- for (int i = 0; i < headers.length(); i++) {
- String fieldName = headers.getFieldName(i);
- String value = headers.getValue(i);
- if ("Cache-Control".equalsIgnoreCase(fieldName)) {
- HeaderParser.parseCacheControl(value, handler);
- } else if ("Pragma".equalsIgnoreCase(fieldName)) {
- if (value.equalsIgnoreCase("no-cache")) {
- noCache = true;
- }
- } else if ("If-None-Match".equalsIgnoreCase(fieldName)) {
- ifNoneMatch = value;
- } else if ("If-Modified-Since".equalsIgnoreCase(fieldName)) {
- ifModifiedSince = value;
- } else if ("Authorization".equalsIgnoreCase(fieldName)) {
- hasAuthorization = true;
- } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
- try {
- contentLength = Integer.parseInt(value);
- } catch (NumberFormatException ignored) {
- }
- } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
- transferEncoding = value;
- } else if ("User-Agent".equalsIgnoreCase(fieldName)) {
- userAgent = value;
- } else if ("Host".equalsIgnoreCase(fieldName)) {
- host = value;
- } else if ("Connection".equalsIgnoreCase(fieldName)) {
- connection = value;
- } else if ("Accept-Encoding".equalsIgnoreCase(fieldName)) {
- acceptEncoding = value;
- } else if ("Content-Type".equalsIgnoreCase(fieldName)) {
- contentType = value;
- } else if ("Proxy-Authorization".equalsIgnoreCase(fieldName)) {
- proxyAuthorization = value;
- }
- }
- }
-
- public boolean isChunked() {
- return "chunked".equalsIgnoreCase(transferEncoding);
- }
-
- public boolean hasConnectionClose() {
- return "close".equalsIgnoreCase(connection);
- }
-
- public URI getUri() {
- return uri;
- }
-
- public RawHeaders getHeaders() {
- return headers;
- }
-
- public boolean isNoCache() {
- return noCache;
- }
-
- public int getMaxAgeSeconds() {
- return maxAgeSeconds;
- }
-
- public int getMaxStaleSeconds() {
- return maxStaleSeconds;
- }
-
- public int getMinFreshSeconds() {
- return minFreshSeconds;
- }
-
- public boolean isOnlyIfCached() {
- return onlyIfCached;
- }
-
- public boolean hasAuthorization() {
- return hasAuthorization;
- }
-
- public int getContentLength() {
- return contentLength;
- }
-
- public String getTransferEncoding() {
- return transferEncoding;
- }
-
- public String getUserAgent() {
- return userAgent;
- }
-
- public String getHost() {
- return host;
- }
-
- public String getConnection() {
- return connection;
- }
-
- public String getAcceptEncoding() {
- return acceptEncoding;
- }
-
- public String getContentType() {
- return contentType;
- }
-
- public String getIfModifiedSince() {
- return ifModifiedSince;
- }
-
- public String getIfNoneMatch() {
- return ifNoneMatch;
- }
-
- public String getProxyAuthorization() {
- return proxyAuthorization;
- }
-
- public void setChunked() {
- if (this.transferEncoding != null) {
- headers.removeAll("Transfer-Encoding");
- }
- headers.add("Transfer-Encoding", "chunked");
- this.transferEncoding = "chunked";
- }
-
- public void setContentLength(int contentLength) {
- if (this.contentLength != -1) {
- headers.removeAll("Content-Length");
- }
- headers.add("Content-Length", Integer.toString(contentLength));
- this.contentLength = contentLength;
- }
-
- public void setUserAgent(String userAgent) {
- if (this.userAgent != null) {
- headers.removeAll("User-Agent");
- }
- headers.add("User-Agent", userAgent);
- this.userAgent = userAgent;
- }
-
- public void setHost(String host) {
- if (this.host != null) {
- headers.removeAll("Host");
- }
- headers.add("Host", host);
- this.host = host;
- }
-
- public void setConnection(String connection) {
- if (this.connection != null) {
- headers.removeAll("Connection");
- }
- headers.add("Connection", connection);
- this.connection = connection;
- }
-
- public void setAcceptEncoding(String acceptEncoding) {
- if (this.acceptEncoding != null) {
- headers.removeAll("Accept-Encoding");
- }
- headers.add("Accept-Encoding", acceptEncoding);
- this.acceptEncoding = acceptEncoding;
- }
-
- public void setContentType(String contentType) {
- if (this.contentType != null) {
- headers.removeAll("Content-Type");
- }
- headers.add("Content-Type", contentType);
- this.contentType = contentType;
- }
-
- public void setIfModifiedSince(Date date) {
- if (ifModifiedSince != null) {
- headers.removeAll("If-Modified-Since");
- }
- String formattedDate = HttpDate.format(date);
- headers.add("If-Modified-Since", formattedDate);
- ifModifiedSince = formattedDate;
- }
-
- public void setIfNoneMatch(String ifNoneMatch) {
- if (this.ifNoneMatch != null) {
- headers.removeAll("If-None-Match");
- }
- headers.add("If-None-Match", ifNoneMatch);
- this.ifNoneMatch = ifNoneMatch;
- }
-
- /**
- * Returns true if the request contains conditions that save the server from
- * sending a response that the client has locally. When the caller adds
- * conditions, this cache won't participate in the request.
- */
- public boolean hasConditions() {
- return ifModifiedSince != null || ifNoneMatch != null;
- }
-
- public void addCookies(Map<String, List<String>> allCookieHeaders) {
- for (Map.Entry<String, List<String>> entry : allCookieHeaders.entrySet()) {
- String key = entry.getKey();
- if ("Cookie".equalsIgnoreCase(key) || "Cookie2".equalsIgnoreCase(key)) {
- headers.addAll(key, entry.getValue());
- }
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/ResponseHeaders.java b/luni/src/main/java/libcore/net/http/ResponseHeaders.java
deleted file mode 100644
index c0b4200..0000000
--- a/luni/src/main/java/libcore/net/http/ResponseHeaders.java
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * 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 libcore.net.http;
-
-import java.net.HttpURLConnection;
-import java.net.ResponseSource;
-import java.net.URI;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.TimeUnit;
-import libcore.util.Objects;
-
-/**
- * Parsed HTTP response headers.
- */
-public final class ResponseHeaders {
-
- /** HTTP header name for the local time when the request was sent. */
- private static final String SENT_MILLIS = "X-Android-Sent-Millis";
-
- /** HTTP header name for the local time when the response was received. */
- private static final String RECEIVED_MILLIS = "X-Android-Received-Millis";
-
- private final URI uri;
- private final RawHeaders headers;
-
- /** The server's time when this response was served, if known. */
- private Date servedDate;
-
- /** The last modified date of the response, if known. */
- private Date lastModified;
-
- /**
- * The expiration date of the response, if known. If both this field and the
- * max age are set, the max age is preferred.
- */
- private Date expires;
-
- /**
- * Extension header set by HttpURLConnectionImpl specifying the timestamp
- * when the HTTP request was first initiated.
- */
- private long sentRequestMillis;
-
- /**
- * Extension header set by HttpURLConnectionImpl specifying the timestamp
- * when the HTTP response was first received.
- */
- private long receivedResponseMillis;
-
- /**
- * In the response, this field's name "no-cache" is misleading. It doesn't
- * prevent us from caching the response; it only means we have to validate
- * the response with the origin server before returning it. We can do this
- * with a conditional get.
- */
- private boolean noCache;
-
- /** If true, this response should not be cached. */
- private boolean noStore;
-
- /**
- * The duration past the response's served date that it can be served
- * without validation.
- */
- private int maxAgeSeconds = -1;
-
- /**
- * The "s-maxage" directive is the max age for shared caches. Not to be
- * confused with "max-age" for non-shared caches, As in Firefox and Chrome,
- * this directive is not honored by this cache.
- */
- private int sMaxAgeSeconds = -1;
-
- /**
- * This request header field's name "only-if-cached" is misleading. It
- * actually means "do not use the network". It is set by a client who only
- * wants to make a request if it can be fully satisfied by the cache.
- * Cached responses that would require validation (ie. conditional gets) are
- * not permitted if this header is set.
- */
- private boolean isPublic;
- private boolean mustRevalidate;
- private String etag;
- private int ageSeconds = -1;
-
- /** Case-insensitive set of field names. */
- private Set<String> varyFields = Collections.emptySet();
-
- private String contentEncoding;
- private String transferEncoding;
- private int contentLength = -1;
- private String connection;
-
- public ResponseHeaders(URI uri, RawHeaders headers) {
- this.uri = uri;
- this.headers = headers;
-
- HeaderParser.CacheControlHandler handler = new HeaderParser.CacheControlHandler() {
- @Override public void handle(String directive, String parameter) {
- if (directive.equalsIgnoreCase("no-cache")) {
- noCache = true;
- } else if (directive.equalsIgnoreCase("no-store")) {
- noStore = true;
- } else if (directive.equalsIgnoreCase("max-age")) {
- maxAgeSeconds = HeaderParser.parseSeconds(parameter);
- } else if (directive.equalsIgnoreCase("s-maxage")) {
- sMaxAgeSeconds = HeaderParser.parseSeconds(parameter);
- } else if (directive.equalsIgnoreCase("public")) {
- isPublic = true;
- } else if (directive.equalsIgnoreCase("must-revalidate")) {
- mustRevalidate = true;
- }
- }
- };
-
- for (int i = 0; i < headers.length(); i++) {
- String fieldName = headers.getFieldName(i);
- String value = headers.getValue(i);
- if ("Cache-Control".equalsIgnoreCase(fieldName)) {
- HeaderParser.parseCacheControl(value, handler);
- } else if ("Date".equalsIgnoreCase(fieldName)) {
- servedDate = HttpDate.parse(value);
- } else if ("Expires".equalsIgnoreCase(fieldName)) {
- expires = HttpDate.parse(value);
- } else if ("Last-Modified".equalsIgnoreCase(fieldName)) {
- lastModified = HttpDate.parse(value);
- } else if ("ETag".equalsIgnoreCase(fieldName)) {
- etag = value;
- } else if ("Pragma".equalsIgnoreCase(fieldName)) {
- if (value.equalsIgnoreCase("no-cache")) {
- noCache = true;
- }
- } else if ("Age".equalsIgnoreCase(fieldName)) {
- ageSeconds = HeaderParser.parseSeconds(value);
- } else if ("Vary".equalsIgnoreCase(fieldName)) {
- // Replace the immutable empty set with something we can mutate.
- if (varyFields.isEmpty()) {
- varyFields = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
- }
- for (String varyField : value.split(",")) {
- varyFields.add(varyField.trim());
- }
- } else if ("Content-Encoding".equalsIgnoreCase(fieldName)) {
- contentEncoding = value;
- } else if ("Transfer-Encoding".equalsIgnoreCase(fieldName)) {
- transferEncoding = value;
- } else if ("Content-Length".equalsIgnoreCase(fieldName)) {
- try {
- contentLength = Integer.parseInt(value);
- } catch (NumberFormatException ignored) {
- }
- } else if ("Connection".equalsIgnoreCase(fieldName)) {
- connection = value;
- } else if (SENT_MILLIS.equalsIgnoreCase(fieldName)) {
- sentRequestMillis = Long.parseLong(value);
- } else if (RECEIVED_MILLIS.equalsIgnoreCase(fieldName)) {
- receivedResponseMillis = Long.parseLong(value);
- }
- }
- }
-
- public boolean isContentEncodingGzip() {
- return "gzip".equalsIgnoreCase(contentEncoding);
- }
-
- public void stripContentEncoding() {
- contentEncoding = null;
- headers.removeAll("Content-Encoding");
- }
-
- public void stripContentLength() {
- contentLength = -1;
- headers.removeAll("Content-Length");
- }
-
- public boolean isChunked() {
- return "chunked".equalsIgnoreCase(transferEncoding);
- }
-
- public boolean hasConnectionClose() {
- return "close".equalsIgnoreCase(connection);
- }
-
- public URI getUri() {
- return uri;
- }
-
- public RawHeaders getHeaders() {
- return headers;
- }
-
- public Date getServedDate() {
- return servedDate;
- }
-
- public Date getLastModified() {
- return lastModified;
- }
-
- public Date getExpires() {
- return expires;
- }
-
- public boolean isNoCache() {
- return noCache;
- }
-
- public boolean isNoStore() {
- return noStore;
- }
-
- public int getMaxAgeSeconds() {
- return maxAgeSeconds;
- }
-
- public int getSMaxAgeSeconds() {
- return sMaxAgeSeconds;
- }
-
- public boolean isPublic() {
- return isPublic;
- }
-
- public boolean isMustRevalidate() {
- return mustRevalidate;
- }
-
- public String getEtag() {
- return etag;
- }
-
- public Set<String> getVaryFields() {
- return varyFields;
- }
-
- public String getContentEncoding() {
- return contentEncoding;
- }
-
- public int getContentLength() {
- return contentLength;
- }
-
- public String getConnection() {
- return connection;
- }
-
- public void setLocalTimestamps(long sentRequestMillis, long receivedResponseMillis) {
- this.sentRequestMillis = sentRequestMillis;
- headers.add(SENT_MILLIS, Long.toString(sentRequestMillis));
- this.receivedResponseMillis = receivedResponseMillis;
- headers.add(RECEIVED_MILLIS, Long.toString(receivedResponseMillis));
- }
-
- /**
- * Returns the current age of the response, in milliseconds. The calculation
- * is specified by RFC 2616, 13.2.3 Age Calculations.
- */
- private long computeAge(long nowMillis) {
- long apparentReceivedAge = servedDate != null
- ? Math.max(0, receivedResponseMillis - servedDate.getTime())
- : 0;
- long receivedAge = ageSeconds != -1
- ? Math.max(apparentReceivedAge, TimeUnit.SECONDS.toMillis(ageSeconds))
- : apparentReceivedAge;
- long responseDuration = receivedResponseMillis - sentRequestMillis;
- long residentDuration = nowMillis - receivedResponseMillis;
- return receivedAge + responseDuration + residentDuration;
- }
-
- /**
- * Returns the number of milliseconds that the response was fresh for,
- * starting from the served date.
- */
- private long computeFreshnessLifetime() {
- if (maxAgeSeconds != -1) {
- return TimeUnit.SECONDS.toMillis(maxAgeSeconds);
- } else if (expires != null) {
- long servedMillis = servedDate != null ? servedDate.getTime() : receivedResponseMillis;
- long delta = expires.getTime() - servedMillis;
- return delta > 0 ? delta : 0;
- } else if (lastModified != null && uri.getRawQuery() == null) {
- /*
- * As recommended by the HTTP RFC and implemented in Firefox, the
- * max age of a document should be defaulted to 10% of the
- * document's age at the time it was served. Default expiration
- * dates aren't used for URIs containing a query.
- */
- long servedMillis = servedDate != null ? servedDate.getTime() : sentRequestMillis;
- long delta = servedMillis - lastModified.getTime();
- return delta > 0 ? (delta / 10) : 0;
- }
- return 0;
- }
-
- /**
- * Returns true if computeFreshnessLifetime used a heuristic. If we used a
- * heuristic to serve a cached response older than 24 hours, we are required
- * to attach a warning.
- */
- private boolean isFreshnessLifetimeHeuristic() {
- return maxAgeSeconds == -1 && expires == null;
- }
-
- /**
- * Returns true if this response can be stored to later serve another
- * request.
- */
- public boolean isCacheable(RequestHeaders request) {
- /*
- * Always go to network for uncacheable response codes (RFC 2616, 13.4),
- * This implementation doesn't support caching partial content.
- */
- int responseCode = headers.getResponseCode();
- if (responseCode != HttpURLConnection.HTTP_OK
- && responseCode != HttpURLConnection.HTTP_NOT_AUTHORITATIVE
- && responseCode != HttpURLConnection.HTTP_MULT_CHOICE
- && responseCode != HttpURLConnection.HTTP_MOVED_PERM
- && responseCode != HttpURLConnection.HTTP_GONE) {
- return false;
- }
-
- /*
- * Responses to authorized requests aren't cacheable unless they include
- * a 'public', 'must-revalidate' or 's-maxage' directive.
- */
- if (request.hasAuthorization()
- && !isPublic
- && !mustRevalidate
- && sMaxAgeSeconds == -1) {
- return false;
- }
-
- if (noStore) {
- return false;
- }
-
- return true;
- }
-
- /**
- * Returns true if a Vary header contains an asterisk. Such responses cannot
- * be cached.
- */
- public boolean hasVaryAll() {
- return varyFields.contains("*");
- }
-
- /**
- * Returns true if none of the Vary headers on this response have changed
- * between {@code cachedRequest} and {@code newRequest}.
- */
- public boolean varyMatches(Map<String, List<String>> cachedRequest,
- Map<String, List<String>> newRequest) {
- for (String field : varyFields) {
- if (!Objects.equal(cachedRequest.get(field), newRequest.get(field))) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Returns the source to satisfy {@code request} given this cached response.
- */
- public ResponseSource chooseResponseSource(long nowMillis, RequestHeaders request) {
- /*
- * If this response shouldn't have been stored, it should never be used
- * as a response source. This check should be redundant as long as the
- * persistence store is well-behaved and the rules are constant.
- */
- if (!isCacheable(request)) {
- return ResponseSource.NETWORK;
- }
-
- if (request.isNoCache() || request.hasConditions()) {
- return ResponseSource.NETWORK;
- }
-
- long ageMillis = computeAge(nowMillis);
- long freshMillis = computeFreshnessLifetime();
-
- if (request.getMaxAgeSeconds() != -1) {
- freshMillis = Math.min(freshMillis,
- TimeUnit.SECONDS.toMillis(request.getMaxAgeSeconds()));
- }
-
- long minFreshMillis = 0;
- if (request.getMinFreshSeconds() != -1) {
- minFreshMillis = TimeUnit.SECONDS.toMillis(request.getMinFreshSeconds());
- }
-
- long maxStaleMillis = 0;
- if (!mustRevalidate && request.getMaxStaleSeconds() != -1) {
- maxStaleMillis = TimeUnit.SECONDS.toMillis(request.getMaxStaleSeconds());
- }
-
- if (!noCache && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) {
- if (ageMillis + minFreshMillis >= freshMillis) {
- headers.add("Warning", "110 HttpURLConnection \"Response is stale\"");
- }
- if (ageMillis > TimeUnit.HOURS.toMillis(24) && isFreshnessLifetimeHeuristic()) {
- headers.add("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
- }
- return ResponseSource.CACHE;
- }
-
- if (lastModified != null) {
- request.setIfModifiedSince(lastModified);
- } else if (servedDate != null) {
- request.setIfModifiedSince(servedDate);
- }
-
- if (etag != null) {
- request.setIfNoneMatch(etag);
- }
-
- return request.hasConditions()
- ? ResponseSource.CONDITIONAL_CACHE
- : ResponseSource.NETWORK;
- }
-
- /**
- * Returns true if this cached response should be used; false if the
- * network response should be used.
- */
- public boolean validate(ResponseHeaders networkResponse) {
- if (networkResponse.headers.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
- return true;
- }
-
- /*
- * The HTTP spec says that if the network's response is older than our
- * cached response, we may return the cache's response. Like Chrome (but
- * unlike Firefox), this client prefers to return the newer response.
- */
- if (lastModified != null
- && networkResponse.lastModified != null
- && networkResponse.lastModified.getTime() < lastModified.getTime()) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Combines this cached header with a network header as defined by RFC 2616,
- * 13.5.3.
- */
- public ResponseHeaders combine(ResponseHeaders network) {
- RawHeaders result = new RawHeaders();
- result.setStatusLine(headers.getStatusLine());
-
- for (int i = 0; i < headers.length(); i++) {
- String fieldName = headers.getFieldName(i);
- String value = headers.getValue(i);
- if (fieldName.equals("Warning") && value.startsWith("1")) {
- continue; // drop 100-level freshness warnings
- }
- if (!isEndToEnd(fieldName) || network.headers.get(fieldName) == null) {
- result.add(fieldName, value);
- }
- }
-
- for (int i = 0; i < network.headers.length(); i++) {
- String fieldName = network.headers.getFieldName(i);
- if (isEndToEnd(fieldName)) {
- result.add(fieldName, network.headers.getValue(i));
- }
- }
-
- return new ResponseHeaders(uri, result);
- }
-
- /**
- * Returns true if {@code fieldName} is an end-to-end HTTP header, as
- * defined by RFC 2616, 13.5.1.
- */
- private static boolean isEndToEnd(String fieldName) {
- return !fieldName.equalsIgnoreCase("Connection")
- && !fieldName.equalsIgnoreCase("Keep-Alive")
- && !fieldName.equalsIgnoreCase("Proxy-Authenticate")
- && !fieldName.equalsIgnoreCase("Proxy-Authorization")
- && !fieldName.equalsIgnoreCase("TE")
- && !fieldName.equalsIgnoreCase("Trailers")
- && !fieldName.equalsIgnoreCase("Transfer-Encoding")
- && !fieldName.equalsIgnoreCase("Upgrade");
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java b/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
deleted file mode 100644
index 67bb5b8..0000000
--- a/luni/src/main/java/libcore/net/http/RetryableOutputStream.java
+++ /dev/null
@@ -1,72 +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.net.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Arrays;
-
-/**
- * An HTTP request body that's completely buffered in memory. This allows
- * the post body to be transparently re-sent if the HTTP request must be
- * sent multiple times.
- */
-final class RetryableOutputStream extends AbstractHttpOutputStream {
- private final int limit;
- private final ByteArrayOutputStream content;
-
- public RetryableOutputStream(int limit) {
- this.limit = limit;
- this.content = new ByteArrayOutputStream(limit);
- }
-
- public RetryableOutputStream() {
- this.limit = -1;
- this.content = new ByteArrayOutputStream();
- }
-
- @Override public synchronized void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- if (content.size() < limit) {
- throw new IOException("content-length promised "
- + limit + " bytes, but received " + content.size());
- }
- }
-
- @Override public synchronized void write(byte[] buffer, int offset, int count)
- throws IOException {
- checkNotClosed();
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
- if (limit != -1 && content.size() > limit - count) {
- throw new IOException("exceeded content-length limit of " + limit + " bytes");
- }
- content.write(buffer, offset, count);
- }
-
- public synchronized int contentLength() throws IOException {
- close();
- return content.size();
- }
-
- public void writeToSocket(OutputStream socketOut) throws IOException {
- content.writeTo(socketOut);
- }
-}
diff --git a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java b/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
deleted file mode 100644
index a8224a3..0000000
--- a/luni/src/main/java/libcore/net/http/UnknownLengthHttpInputStream.java
+++ /dev/null
@@ -1,65 +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.net.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.CacheRequest;
-import java.util.Arrays;
-
-/**
- * An HTTP payload terminated by the end of the socket stream.
- */
-final class UnknownLengthHttpInputStream extends AbstractHttpInputStream {
- private boolean inputExhausted;
-
- UnknownLengthHttpInputStream(InputStream is, CacheRequest cacheRequest,
- HttpEngine httpEngine) throws IOException {
- super(is, httpEngine, cacheRequest);
- }
-
- @Override public int read(byte[] buffer, int offset, int count) throws IOException {
- Arrays.checkOffsetAndCount(buffer.length, offset, count);
- checkNotClosed();
- if (in == null || inputExhausted) {
- return -1;
- }
- int read = in.read(buffer, offset, count);
- if (read == -1) {
- inputExhausted = true;
- endOfInput(false);
- return -1;
- }
- cacheWrite(buffer, offset, read);
- return read;
- }
-
- @Override public int available() throws IOException {
- checkNotClosed();
- return in == null ? 0 : in.available();
- }
-
- @Override public void close() throws IOException {
- if (closed) {
- return;
- }
- closed = true;
- if (!inputExhausted) {
- unexpectedEndOfInput();
- }
- }
-}
diff --git a/luni/src/main/java/libcore/net/url/FtpURLConnection.java b/luni/src/main/java/libcore/net/url/FtpURLConnection.java
index e168428..7594c3a 100644
--- a/luni/src/main/java/libcore/net/url/FtpURLConnection.java
+++ b/luni/src/main/java/libcore/net/url/FtpURLConnection.java
@@ -35,7 +35,7 @@
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.security.Permission;
import java.util.ArrayList;
import java.util.Iterator;
@@ -350,7 +350,7 @@
}
code[i] = (byte) tmp;
}
- replyCode = new String(code, 0, code.length, Charsets.ISO_8859_1);
+ replyCode = new String(code, 0, code.length, StandardCharsets.ISO_8859_1);
boolean multiline = false;
if (ctrlInput.read() == '-') {
@@ -497,6 +497,6 @@
}
private void write(String command) throws IOException {
- ctrlOutput.write(command.getBytes(Charsets.ISO_8859_1));
+ ctrlOutput.write(command.getBytes(StandardCharsets.ISO_8859_1));
}
}
diff --git a/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java b/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
index 9a2c898..762f0e2 100644
--- a/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
+++ b/luni/src/main/java/libcore/net/url/JarURLConnectionImpl.java
@@ -47,7 +47,7 @@
*/
public class JarURLConnectionImpl extends JarURLConnection {
- static HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
+ private static final HashMap<URL, JarFile> jarCache = new HashMap<URL, JarFile>();
private URL jarFileURL;
@@ -67,8 +67,7 @@
* @throws IOException
* if there is a problem opening the connection.
*/
- public JarURLConnectionImpl(URL url) throws MalformedURLException,
- IOException {
+ public JarURLConnectionImpl(URL url) throws MalformedURLException, IOException {
super(url);
jarFileURL = getJarFileURL();
jarFileURLConnection = jarFileURL.openConnection();
@@ -89,8 +88,6 @@
/**
* Returns the Jar file referred by this {@code URLConnection}.
*
- * @return the JAR file referenced by this connection
- *
* @throws IOException
* thrown if an IO error occurs while connecting to the
* resource.
@@ -108,13 +105,12 @@
* if an IO error occurs while connecting to the resource.
*/
private void findJarFile() throws IOException {
- JarFile jar = null;
if (getUseCaches()) {
synchronized (jarCache) {
jarFile = jarCache.get(jarFileURL);
}
if (jarFile == null) {
- jar = openJarFile();
+ JarFile jar = openJarFile();
synchronized (jarCache) {
jarFile = jarCache.get(jarFileURL);
if (jarFile == null) {
@@ -134,7 +130,7 @@
}
}
- JarFile openJarFile() throws IOException {
+ private JarFile openJarFile() throws IOException {
if (jarFileURL.getProtocol().equals("file")) {
String decodedFile = UriCodec.decode(jarFileURL.getFile());
return new JarFile(new File(decodedFile), true, ZipFile.OPEN_READ);
@@ -346,26 +342,6 @@
jarFileURLConnection.setDefaultUseCaches(defaultusecaches);
}
- /**
- * Closes the cached files.
- */
- public static void closeCachedFiles() {
- Set<Map.Entry<URL, JarFile>> s = jarCache.entrySet();
- synchronized (jarCache) {
- Iterator<Map.Entry<URL, JarFile>> i = s.iterator();
- while (i.hasNext()) {
- try {
- ZipFile zip = i.next().getValue();
- if (zip != null) {
- zip.close();
- }
- } catch (IOException e) {
- // Ignored
- }
- }
- }
- }
-
private class JarURLConnectionInputStream extends FilterInputStream {
final JarFile jarFile;
diff --git a/luni/src/main/java/libcore/reflect/AnnotationAccess.java b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
new file mode 100644
index 0000000..fe740de
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/AnnotationAccess.java
@@ -0,0 +1,794 @@
+/*
+ * 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 libcore.reflect;
+
+import com.android.dex.ClassDef;
+import com.android.dex.Dex;
+import com.android.dex.EncodedValueReader;
+import com.android.dex.FieldId;
+import com.android.dex.MethodId;
+import com.android.dex.ProtoId;
+import com.android.dex.TypeList;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Inherited;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import libcore.util.EmptyArray;
+
+/**
+ * Look up annotations from a dex file.
+ */
+public final class AnnotationAccess {
+ private AnnotationAccess() {
+ }
+
+ /*
+ * Classes like arrays, primitives and proxies will not have a Dex file.
+ * Such classes never have annotations.
+ */
+
+ private static final Class<?>[] NO_ARGUMENTS = null;
+ @SuppressWarnings("unused")
+ private static final byte VISIBILITY_BUILD = 0x00;
+ private static final byte VISIBILITY_RUNTIME = 0x01;
+ @SuppressWarnings("unused")
+ private static final byte VISIBILITY_SYSTEM = 0x02;
+
+ /*
+ * Class annotations. This includes declared class annotations plus
+ * annotations on the superclass that have @Inherited.
+ */
+
+ public static <A extends java.lang.annotation.Annotation> A getAnnotation(
+ Class<?> c, Class<A> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ A annotation = getDeclaredAnnotation(c, annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+
+ if (isInherited(annotationType)) {
+ for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ annotation = getDeclaredAnnotation(sup, annotationType);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns true if {@code annotationType} annotations on the superclass
+ * apply to subclasses that don't have another annotation of the same
+ * type.
+ */
+ private static boolean isInherited(Class<? extends Annotation> annotationType) {
+ return isDeclaredAnnotationPresent(annotationType, Inherited.class);
+ }
+
+ public static Annotation[] getAnnotations(Class<?> c) {
+ /*
+ * We need to get the annotations declared on this class, plus the
+ * annotations from superclasses that have the "@Inherited" annotation
+ * set. We create a temporary map to use while we accumulate the
+ * annotations and convert it to an array at the end.
+ *
+ * It's possible to have duplicates when annotations are inherited.
+ * We use a Map to filter those out.
+ *
+ * HashMap might be overkill here.
+ */
+ HashMap<Class<?>, Annotation> map = new HashMap<Class<?>, Annotation>();
+ for (Annotation declaredAnnotation : getDeclaredAnnotations(c)) {
+ map.put(declaredAnnotation.annotationType(), declaredAnnotation);
+ }
+ for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ for (Annotation declaredAnnotation : getDeclaredAnnotations(sup)) {
+ Class<? extends Annotation> clazz = declaredAnnotation.annotationType();
+ if (!map.containsKey(clazz) && isInherited(clazz)) {
+ map.put(clazz, declaredAnnotation);
+ }
+ }
+ }
+
+ /* convert annotation values from HashMap to array */
+ Collection<Annotation> coll = map.values();
+ return coll.toArray(new Annotation[coll.size()]);
+ }
+
+ /**
+ * Returns true if {@code c} is annotated by {@code annotationType}.
+ */
+ public static boolean isAnnotationPresent(
+ Class<?> c, Class<? extends Annotation> annotationType) {
+ if (annotationType == null) {
+ throw new NullPointerException("annotationType == null");
+ }
+
+ if (isDeclaredAnnotationPresent(c, annotationType)) {
+ return true;
+ }
+
+ if (isInherited(annotationType)) {
+ for (Class<?> sup = c.getSuperclass(); sup != null; sup = sup.getSuperclass()) {
+ if (isDeclaredAnnotationPresent(sup, annotationType)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /*
+ * Class, Field, Method, Constructor and Parameter annotations
+ */
+
+ /**
+ * Returns the annotations on {@code element}.
+ */
+ public static List<Annotation> getDeclaredAnnotations(AnnotatedElement element) {
+ int offset = getAnnotationSetOffset(element);
+ return annotationSetToAnnotations(getDexClass(element), offset);
+ }
+
+ /**
+ * Returns the annotation if it exists.
+ */
+ public static <A extends Annotation> A getDeclaredAnnotation(
+ AnnotatedElement element, Class<A> annotationClass) {
+ com.android.dex.Annotation a = getMethodAnnotation(element, annotationClass);
+ return a != null
+ ? toAnnotationInstance(getDexClass(element), annotationClass, a)
+ : null;
+ }
+
+ /**
+ * Returns true if the annotation exists.
+ */
+ public static boolean isDeclaredAnnotationPresent(
+ AnnotatedElement element, Class<? extends Annotation> annotationClass) {
+ return getMethodAnnotation(element, annotationClass) != null;
+ }
+
+ private static com.android.dex.Annotation getMethodAnnotation(
+ AnnotatedElement element, Class<? extends Annotation> annotationClass) {
+ Class<?> dexClass = getDexClass(element);
+ Dex dex = dexClass.getDex();
+ int annotationTypeIndex = getTypeIndex(dex, annotationClass);
+ if (annotationTypeIndex == -1) {
+ return null; // the dex file doesn't use this annotation
+ }
+
+ int annotationSetOffset = getAnnotationSetOffset(element);
+ return getAnnotationFromAnnotationSet(dex, annotationSetOffset, annotationTypeIndex);
+ }
+
+ /**
+ * @param element a class, a field, a method or a constructor.
+ */
+ private static int getAnnotationSetOffset(AnnotatedElement element) {
+ Class<?> dexClass = getDexClass(element);
+ int directoryOffset = getDirectoryOffset(dexClass);
+ if (directoryOffset == 0) {
+ return 0; // nothing on this class has annotations
+ }
+
+ Dex.Section directoryIn = dexClass.getDex().open(directoryOffset);
+ int classSetOffset = directoryIn.readInt();
+ if (element instanceof Class) {
+ return classSetOffset;
+ }
+
+ int fieldsSize = directoryIn.readInt();
+ int methodsSize = directoryIn.readInt();
+ directoryIn.readInt(); // parameters size
+
+ int fieldIndex = element instanceof Field ? ((Field) element).getDexFieldIndex() : -1;
+ for (int i = 0; i < fieldsSize; i++) {
+ int candidateFieldIndex = directoryIn.readInt();
+ int annotationSetOffset = directoryIn.readInt();
+ if (candidateFieldIndex == fieldIndex) {
+ return annotationSetOffset;
+ }
+ }
+ // we must read all fields prior to methods, if we were searching for a field then we missed
+ if (element instanceof Field) {
+ return 0;
+ }
+
+ int methodIndex= element instanceof Method ? ((Method) element).getDexMethodIndex()
+ : ((Constructor<?>) element).getDexMethodIndex();
+ for (int i = 0; i < methodsSize; i++) {
+ int candidateMethodIndex = directoryIn.readInt();
+ int annotationSetOffset = directoryIn.readInt();
+ if (candidateMethodIndex == methodIndex) {
+ return annotationSetOffset;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns {@code element} if it is a class; and the class declaring
+ * {@code element} otherwise. The dex file of the returned class also
+ * defines {@code element}.
+ */
+ private static Class<?> getDexClass(AnnotatedElement element) {
+ return element instanceof Class
+ ? ((Class<?>) element)
+ : ((Member) element).getDeclaringClass();
+ }
+
+ public static int getFieldIndex(Class<?> declaringClass, Class<?> type, String name) {
+ Dex dex = declaringClass.getDex();
+ int declaringClassIndex = getTypeIndex(dex, declaringClass);
+ int typeIndex = getTypeIndex(dex, type);
+ int nameIndex = getStringIndex(dex, name);
+ FieldId fieldId = new FieldId(dex, declaringClassIndex, typeIndex, nameIndex);
+ return Collections.binarySearch(dex.fieldIds(), 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);
+ MethodId methodId = new MethodId(dex, declaringClassIndex, protoIndex, nameIndex);
+ return Collections.binarySearch(dex.methodIds(), methodId);
+ }
+
+ /**
+ * Returns the parameter annotations on {@code member}.
+ */
+ public static Annotation[][] getParameterAnnotations(Member member) {
+ Class<?> declaringClass = member.getDeclaringClass();
+ 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);
+ if (directoryOffset == 0) {
+ return new Annotation[typesCount][0]; // nothing on this class has annotations
+ }
+
+ Dex.Section directoryIn = dex.open(directoryOffset);
+ directoryIn.readInt(); // class annotations
+ int fieldsSize = directoryIn.readInt();
+ int methodsSize = directoryIn.readInt();
+ int parametersSize = directoryIn.readInt();
+
+ for (int i = 0; i < fieldsSize; i++) {
+ directoryIn.readInt(); // field_index
+ directoryIn.readInt(); // annotation_set
+ }
+
+ for (int i = 0; i < methodsSize; i++) {
+ directoryIn.readInt(); // method_index
+ directoryIn.readInt(); // annotation_set
+ }
+
+ for (int i = 0; i < parametersSize; i++) {
+ int candidateMethodDexIndex = directoryIn.readInt();
+ int annotationSetRefListOffset = directoryIn.readInt();
+ if (candidateMethodDexIndex != methodDexIndex) {
+ continue;
+ }
+
+ Dex.Section refList = dex.open(annotationSetRefListOffset);
+ int parameterCount = refList.readInt();
+ Annotation[][] result = new Annotation[parameterCount][];
+ for (int p = 0; p < parameterCount; p++) {
+ int annotationSetOffset = refList.readInt();
+ List<Annotation> annotations
+ = annotationSetToAnnotations(declaringClass, annotationSetOffset);
+ result[p] = annotations.toArray(new Annotation[annotations.size()]);
+ }
+ return result;
+ }
+
+ return new Annotation[typesCount][0];
+ }
+
+ /*
+ * System annotations.
+ */
+
+ public static Object getDefaultValue(Method method) {
+ /*
+ * Dex represents this with @AnnotationDefault on annotations that have
+ * default values:
+ *
+ * @AnnotationDefault(value=@Foo(a=7))
+ * public @interface Foo {
+ * int a() default 7;
+ * int b();
+ * }
+ */
+
+ Class<?> annotationClass = method.getDeclaringClass();
+ Dex dex = annotationClass.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, annotationClass, "Ldalvik/annotation/AnnotationDefault;");
+ if (reader == null) {
+ return null;
+ }
+
+ int fieldCount = reader.readAnnotation();
+ if (reader.getAnnotationType() != getTypeIndex(dex, annotationClass)) {
+ throw new AssertionError("annotation value type != annotation class");
+ }
+
+ int methodNameIndex = Collections.binarySearch(dex.strings(), method.getName());
+ for (int i = 0; i < fieldCount; i++) {
+ int candidateNameIndex = reader.readAnnotationName();
+ if (candidateNameIndex == methodNameIndex) {
+ Class<?> returnType = method.getReturnType();
+ return decodeValue(annotationClass, returnType, dex, reader);
+ } else {
+ reader.skipValue();
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the class of which {@code c} is a direct member. If {@code c} is
+ * defined in a method or constructor, this is not transitive.
+ */
+ public static Class<?> getDeclaringClass(Class<?> c) {
+ /*
+ * public class Bar {
+ * @EnclosingClass(value=Bar)
+ * public class Foo {}
+ * }
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, c, "Ldalvik/annotation/EnclosingClass;");
+ if (reader == null) {
+ return null;
+ }
+ return indexToType(c, dex, reader.readType());
+ }
+
+ public static AccessibleObject getEnclosingMethodOrConstructor(Class<?> c) {
+ /*
+ * public class Bar {
+ * public void quux(String s, int i) {
+ * @EnclosingMethod(value=Bar.quux(String,int))
+ * class Foo {}
+ * }
+ * }
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, c, "Ldalvik/annotation/EnclosingMethod;");
+ if (reader == null) {
+ return null;
+ }
+ return indexToMethod(c, dex, reader.readMethod());
+ }
+
+ public static Class<?>[] getMemberClasses(Class<?> c) {
+ /*
+ * @MemberClasses(value=[Bar, Baz])
+ * public class Foo {
+ * class Bar {}
+ * class Baz {}
+ * }
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, c, "Ldalvik/annotation/MemberClasses;");
+ if (reader == null) {
+ return EmptyArray.CLASS;
+ }
+ return (Class[]) decodeValue(c, Class[].class, dex, reader);
+ }
+
+ /**
+ * @param element a class, a field, a method or a constructor.
+ */
+ public static String getSignature(AnnotatedElement element) {
+ /*
+ * @Signature(value=["Ljava/util/List", "<", "Ljava/lang/String;", ">;"])
+ * List<String> foo;
+ */
+ Class<?> dexClass = getDexClass(element);
+ Dex dex = dexClass.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, element, "Ldalvik/annotation/Signature;");
+ if (reader == null) {
+ return null;
+ }
+ String[] array = (String[]) decodeValue(dexClass, String[].class, dex, reader);
+ StringBuilder result = new StringBuilder();
+ for (String s : array) {
+ result.append(s);
+ }
+ return result.toString();
+ }
+
+ /**
+ * @param element a method or a constructor.
+ */
+ public static Class<?>[] getExceptions(AnnotatedElement element) {
+ /*
+ * @Throws(value=[IOException.class])
+ * void foo() throws IOException;
+ */
+ Class<?> dexClass = getDexClass(element);
+ Dex dex = dexClass.getDex();
+ EncodedValueReader reader = getOnlyAnnotationValue(
+ dex, element, "Ldalvik/annotation/Throws;");
+ if (reader == null) {
+ return EmptyArray.CLASS;
+ }
+ return (Class<?>[]) decodeValue(dexClass, Class[].class, dex, reader);
+ }
+
+ public static int getInnerClassFlags(Class<?> c, int defaultValue) {
+ /*
+ * @InnerClass(accessFlags=0x01,name="Foo")
+ * class Foo {};
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getAnnotationReader(
+ dex, c, "Ldalvik/annotation/InnerClass;", 2);
+ if (reader == null) {
+ return defaultValue;
+ }
+ reader.readAnnotationName(); // accessFlags
+ return reader.readInt();
+ }
+
+ public static String getInnerClassName(Class<?> c) {
+ /*
+ * @InnerClass(accessFlags=0x01,name="Foo")
+ * class Foo {};
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getAnnotationReader(
+ dex, c, "Ldalvik/annotation/InnerClass;", 2);
+ if (reader == null) {
+ return null;
+ }
+ reader.readAnnotationName(); // accessFlags
+ reader.readInt();
+ reader.readAnnotationName(); // name
+ return reader.peek() == EncodedValueReader.ENCODED_NULL
+ ? null
+ : (String) decodeValue(c, String.class, dex, reader);
+ }
+
+ public static boolean isAnonymousClass(Class<?> c) {
+ /*
+ * @InnerClass(accessFlags=0x01,name="Foo")
+ * class Foo {};
+ */
+ Dex dex = c.getDex();
+ EncodedValueReader reader = getAnnotationReader(
+ dex, c, "Ldalvik/annotation/InnerClass;", 2);
+ if (reader == null) {
+ return false;
+ }
+ reader.readAnnotationName(); // accessFlags
+ reader.readInt();
+ reader.readAnnotationName(); // name
+ return reader.peek() == EncodedValueReader.ENCODED_NULL;
+ }
+
+ /*
+ * Dex support.
+ *
+ * Different classes come from different Dex files. This class is careful
+ * to guarantee that Dex-relative indices and encoded values are interpreted
+ * using the Dex that they were read from. Methods that use Dex-relative
+ * values accept that Dex as a parameter or the class from which that Dex
+ * was derived.
+ */
+
+ 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 == null) {
+ return -1;
+ }
+ int typeIndex = Collections.binarySearch(dex.typeNames(), 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) {
+ int annotationSetOffset = getAnnotationSetOffset(element);
+ if (annotationSetOffset == 0) {
+ return null; // no annotations on the class
+ }
+
+ int annotationTypeIndex = Collections.binarySearch(dex.typeNames(), annotationName);
+ com.android.dex.Annotation annotation = getAnnotationFromAnnotationSet(
+ dex, annotationSetOffset, annotationTypeIndex);
+ if (annotation == null) {
+ return null; // no annotation
+ }
+
+ EncodedValueReader reader = annotation.getReader();
+ int fieldCount = reader.readAnnotation();
+ if (reader.getAnnotationType() != annotationTypeIndex) {
+ throw new AssertionError();
+ }
+ if (fieldCount != expectedFieldCount) {
+ return null; // not the expected values on this annotation; give up
+ }
+
+ return reader;
+ }
+
+ /**
+ * Returns a reader ready to read the only value of the annotation on
+ * {@code element}, or null if that annotation doesn't exist.
+ */
+ private static EncodedValueReader getOnlyAnnotationValue(
+ Dex dex, AnnotatedElement element, String annotationName) {
+ EncodedValueReader reader = getAnnotationReader(dex, element, annotationName, 1);
+ if (reader == null) {
+ return null;
+ }
+ reader.readAnnotationName(); // skip the name
+ return reader;
+ }
+
+ private static Class<? extends Annotation> getAnnotationClass(Class<?> context, Dex dex,
+ int typeIndex) {
+ try {
+ @SuppressWarnings("unchecked") // we do a runtime check
+ Class<? extends Annotation> result = (Class<? extends Annotation>) indexToType(context,
+ dex, typeIndex);
+ if (!result.isAnnotation()) {
+ throw new IncompatibleClassChangeError("Expected annotation: " + result.getName());
+ }
+ return result;
+ } catch (NoClassDefFoundError ncdfe) {
+ return null;
+ }
+ }
+
+ 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<?>[] parametersArray = new Class[types.length];
+ for (int i = 0; i < types.length; i++) {
+ parametersArray[i] = indexToType(context, 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;
+ }
+ 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) {
+ if (offset == 0) {
+ return Collections.emptyList(); // no annotations in the set
+ }
+
+ Dex dex = context.getDex();
+ Dex.Section setIn = dex.open(offset); // annotation_set_item
+ int size = setIn.readInt();
+ List<Annotation> result = new ArrayList<Annotation>(size);
+
+ for (int i = 0; i < size; i++) {
+ int annotationOffset = setIn.readInt();
+ Dex.Section annotationIn = dex.open(annotationOffset); // annotation_item
+ com.android.dex.Annotation annotation = annotationIn.readAnnotation();
+ if (annotation.getVisibility() != VISIBILITY_RUNTIME) {
+ continue;
+ }
+ Class<? extends Annotation> annotationClass =
+ getAnnotationClass(context, dex, annotation.getTypeIndex());
+ if (annotationClass != null) {
+ result.add(toAnnotationInstance(context, dex, annotationClass, annotation.getReader()));
+ }
+ }
+ return result;
+ }
+
+ private static <A extends Annotation> A toAnnotationInstance(Class<?> context,
+ Class<A> annotationClass, com.android.dex.Annotation annotation) {
+ return toAnnotationInstance(context, context.getDex(), annotationClass,
+ annotation.getReader());
+ }
+
+ 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())) {
+ throw new AssertionError("annotation value type != return type");
+ }
+ AnnotationMember[] members = new AnnotationMember[fieldCount];
+ for (int i = 0; i < fieldCount; i++) {
+ int name = reader.readAnnotationName();
+ String nameString = dex.strings().get(name);
+ Method method;
+ try {
+ method = annotationClass.getMethod(nameString, NO_ARGUMENTS);
+ } catch (NoSuchMethodException e) {
+ throw new IncompatibleClassChangeError(
+ "Couldn't find " + annotationClass.getName() + "." + nameString);
+ }
+ Class<?> returnType = method.getReturnType();
+ Object value = decodeValue(context, returnType, dex, reader);
+ members[i] = new AnnotationMember(nameString, value, returnType, method);
+ }
+ return AnnotationFactory.createAnnotation(annotationClass, members);
+ }
+
+ private static Object decodeValue(Class<?> context, Class<?> type,
+ Dex dex, EncodedValueReader reader) {
+ if (type.isArray()) {
+ int size = reader.readArray();
+ Class<?> componentType = type.getComponentType();
+ Object array = Array.newInstance(componentType, size);
+ for (int i = 0; i < size; i++) {
+ Array.set(array, i, decodeValue(context, componentType, dex, reader));
+ }
+ return array;
+ } 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);
+ } 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);
+ } else if (type == Class.class) {
+ int index = reader.readType();
+ return indexToType(context, dex, index);
+ } else if (type == byte.class) {
+ return reader.readByte();
+ } else if (type == short.class) {
+ return reader.readShort();
+ } else if (type == int.class) {
+ return reader.readInt();
+ } else if (type == long.class) {
+ return reader.readLong();
+ } else if (type == float.class) {
+ return reader.readFloat();
+ } else if (type == double.class) {
+ return reader.readDouble();
+ } else if (type == char.class) {
+ return reader.readChar();
+ } else if (type == boolean.class) {
+ return reader.readBoolean();
+ } else {
+ // is null legit?
+ throw new AssertionError("Unexpected annotation value type: " + type);
+ }
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java b/luni/src/main/java/libcore/reflect/AnnotationFactory.java
similarity index 79%
rename from luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java
rename to luni/src/main/java/libcore/reflect/AnnotationFactory.java
index 3fd13f5..272754a 100644
--- a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationFactory.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationFactory.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.lang.annotation;
+package libcore.reflect;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -29,8 +29,6 @@
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
-import static org.apache.harmony.lang.annotation.AnnotationMember.ARRAY;
-import static org.apache.harmony.lang.annotation.AnnotationMember.ERROR;
/**
* The annotation implementation based on dynamically generated proxy instances.
@@ -41,7 +39,7 @@
* conforming access to annotation member values and required implementations of
* methods declared in Annotation interface.
*
- * @see android.lang.annotation.AnnotationMember
+ * @see AnnotationMember
* @see java.lang.annotation.Annotation
*
* @author Alexey V. Varlamov, Serguei S. Zapreyev
@@ -50,35 +48,36 @@
@SuppressWarnings({"serial"})
public final class AnnotationFactory implements InvocationHandler, Serializable {
- private static final transient
- Map<Class<? extends Annotation>, AnnotationMember[]>
- cache = new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>();
+ private static final transient Map<Class<? extends Annotation>, AnnotationMember[]> cache =
+ new WeakHashMap<Class<? extends Annotation>, AnnotationMember[]>();
/**
* Reflects specified annotation type and returns an array
* of member element definitions with default values.
*/
- public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType ) {
- AnnotationMember[] desc = cache.get(annotationType);
- if (desc == null) {
- if (!annotationType.isAnnotation()) {
- throw new IllegalArgumentException("Type is not annotation: "
- + annotationType.getName());
+ public static AnnotationMember[] getElementsDescription(Class<? extends Annotation> annotationType) {
+ synchronized (cache) {
+ AnnotationMember[] desc = cache.get(annotationType);
+ if (desc != null) {
+ return desc;
}
- Method[] m = annotationType.getDeclaredMethods();
- desc = new AnnotationMember[m.length];
- int idx = 0;
- for (Method element : m) {
- String name = element.getName();
- Class<?> type = element.getReturnType();
- try {
- desc[idx] = new AnnotationMember(name,
- element.getDefaultValue(), type, element);
- } catch (Throwable t) {
- desc[idx] = new AnnotationMember(name, t, type, element);
- }
- idx++;
+ }
+ if (!annotationType.isAnnotation()) {
+ throw new IllegalArgumentException("Type is not annotation: " + annotationType.getName());
+ }
+ Method[] declaredMethods = annotationType.getDeclaredMethods();
+ AnnotationMember[] desc = new AnnotationMember[declaredMethods.length];
+ for (int i = 0; i < declaredMethods.length; ++i) {
+ Method element = declaredMethods[i];
+ String name = element.getName();
+ Class<?> type = element.getReturnType();
+ try {
+ desc[i] = new AnnotationMember(name, element.getDefaultValue(), type, element);
+ } catch (Throwable t) {
+ desc[i] = new AnnotationMember(name, t, type, element);
}
+ }
+ synchronized (cache) {
cache.put(annotationType, desc);
}
return desc;
@@ -90,13 +89,11 @@
* @param elements name-value pairs representing elements of the annotation
* @return a new annotation instance
*/
- public static Annotation createAnnotation(
- Class<? extends Annotation> annotationType,
- AnnotationMember[] elements)
- {
- AnnotationFactory antn = new AnnotationFactory(annotationType, elements);
- return (Annotation)Proxy.newProxyInstance( annotationType.getClassLoader(),
- new Class[]{annotationType}, antn);
+ public static <A extends Annotation> A createAnnotation(Class<? extends Annotation> annotationType,
+ AnnotationMember[] elements) {
+ AnnotationFactory factory = new AnnotationFactory(annotationType, elements);
+ return (A) Proxy.newProxyInstance(annotationType.getClassLoader(),
+ new Class[]{annotationType}, factory);
}
private final Class<? extends Annotation> klazz;
@@ -118,8 +115,8 @@
} else {
//merge default and actual values
elements = new AnnotationMember[defs.length];
- next: for (int i = elements.length - 1; i >= 0; i-- ){
- for (AnnotationMember val : values){
+ next: for (int i = elements.length - 1; i >= 0; i--) {
+ for (AnnotationMember val : values) {
if (val.name.equals(defs[i].name)) {
elements[i] = val.setDefinition(defs[i]);
continue next;
@@ -134,8 +131,7 @@
* Reads the object, obtains actual member definitions for the annotation type,
* and merges deserialized values with the new definitions.
*/
- private void readObject(ObjectInputStream os) throws IOException,
- ClassNotFoundException {
+ private void readObject(ObjectInputStream os) throws IOException, ClassNotFoundException {
os.defaultReadObject();
// Annotation type members can be changed arbitrarily
// So there may be zombi elements from the previous life;
@@ -145,8 +141,7 @@
// but seems better to keep them for compatibility
AnnotationMember[] defs = getElementsDescription(klazz);
AnnotationMember[] old = elements;
- List<AnnotationMember> merged = new ArrayList<AnnotationMember>(
- defs.length + old.length);
+ List<AnnotationMember> merged = new ArrayList<AnnotationMember>(defs.length + old.length);
nextOld: for (AnnotationMember el1 : old) {
for (AnnotationMember el2 : defs) {
if (el2.name.equals(el1.name)) {
@@ -155,8 +150,8 @@
}
merged.add(el1); //phantom element
}
- nextNew: for (AnnotationMember def : defs){
- for (AnnotationMember val : old){
+ nextNew: for (AnnotationMember def : defs) {
+ for (AnnotationMember val : old) {
if (val.name.equals(def.name)) {
// nothing to do about cached errors (if any)
// anyway they remain relevant to values
@@ -177,7 +172,7 @@
* differ completely from this class.
* @return true if the passed object is equivalent annotation instance,
* false otherwise.
- * @see android.lang.annotation.AnnotationMember#equals(Object)
+ * @see AnnotationMember#equals(Object)
*/
public boolean equals(Object obj) {
if (obj == this) {
@@ -188,12 +183,12 @@
}
Object handler = null;
if (Proxy.isProxyClass(obj.getClass())
- && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory ) {
+ && (handler = Proxy.getInvocationHandler(obj)) instanceof AnnotationFactory) {
AnnotationFactory other = (AnnotationFactory) handler;
if (elements.length != other.elements.length) {
return false;
}
- next: for (AnnotationMember el1 : elements){
+ next: for (AnnotationMember el1 : elements) {
for (AnnotationMember el2 : other.elements) {
if (el1.equals(el2)) {
continue next;
@@ -203,11 +198,11 @@
}
return true;
} else {
- // encountered foreign annotation implementaton
+ // encountered foreign annotation implementation
// so have to obtain element values via invocation
// of corresponding methods
for (final AnnotationMember el : elements) {
- if (el.tag == ERROR) {
+ if (el.tag == AnnotationMember.ERROR) {
// undefined value is incomparable (transcendent)
return false;
}
@@ -216,8 +211,8 @@
el.definingMethod.setAccessible(true);
}
Object otherValue = el.definingMethod.invoke(obj);
- if (otherValue != null ) {
- if (el.tag == ARRAY) {
+ if (otherValue != null) {
+ if (el.tag == AnnotationMember.ARRAY) {
if (!el.equalArrayValue(otherValue)) {
return false;
}
@@ -240,7 +235,7 @@
/**
* Returns a hash code composed as a sum of hash codes of member elements,
* including elements with default values.
- * @see android.lang.annotation.AnnotationMember#hashCode()
+ * @see AnnotationMember#hashCode()
*/
public int hashCode() {
int hash = 0;
@@ -278,8 +273,7 @@
* @throws IllegalArgumentException If the specified method is none of the above
* @return the invocation result
*/
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
Class[] params = method.getParameterTypes();
if (params.length == 0) {
@@ -308,10 +302,9 @@
}
return value;
}
- } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)){
+ } else if (params.length == 1 && params[0] == Object.class && "equals".equals(name)) {
return Boolean.valueOf(equals(args[0]));
}
- throw new IllegalArgumentException(
- "Invalid method for annotation type: " + method);
+ throw new IllegalArgumentException("Invalid method for annotation type: " + method);
}
}
diff --git a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java b/luni/src/main/java/libcore/reflect/AnnotationMember.java
similarity index 98%
rename from luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java
rename to luni/src/main/java/libcore/reflect/AnnotationMember.java
index f64332a..7ca4abf 100644
--- a/luni/src/main/java/org/apache/harmony/lang/annotation/AnnotationMember.java
+++ b/luni/src/main/java/libcore/reflect/AnnotationMember.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.harmony.lang.annotation;
+package libcore.reflect;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -45,13 +45,13 @@
* class-data structures and throwing is delayed until the element
* is requested for value.
*
- * @see android.lang.annotation.AnnotationFactory
+ * @see AnnotationFactory
*
* @author Alexey V. Varlamov, Serguei S. Zapreyev
* @version $Revision$
*/
@SuppressWarnings({"serial"})
-public class AnnotationMember implements Serializable {
+public final class AnnotationMember implements Serializable {
/**
* Tag description of a Throwable value type.
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
similarity index 81%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java
rename to luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
index c9b76b1..ef22576 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForArray.java
+++ b/luni/src/main/java/libcore/reflect/GenericArrayTypeImpl.java
@@ -14,21 +14,21 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Type;
-public final class ImplForArray implements GenericArrayType {
+public final class GenericArrayTypeImpl implements GenericArrayType {
private final Type componentType;
- public ImplForArray(Type componentType) {
+ public GenericArrayTypeImpl(Type componentType) {
this.componentType = componentType;
}
public Type getGenericComponentType() {
try {
- return ((ImplForType)componentType).getResolvedType();
+ return ((ParameterizedTypeImpl)componentType).getResolvedType();
} catch (ClassCastException e) {
return componentType;
}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
similarity index 87%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java
rename to luni/src/main/java/libcore/reflect/GenericSignatureParser.java
index 490daaf..0c94eba 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/GenericSignatureParser.java
+++ b/luni/src/main/java/libcore/reflect/GenericSignatureParser.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
@@ -64,7 +64,9 @@
* VoidDescriptor ::= "V".
* </pre>
*/
-public class GenericSignatureParser {
+public final class GenericSignatureParser {
+
+ // TODO: unify this with InternalNames
public ListOfTypes exceptionTypes;
public ListOfTypes parameterTypes;
@@ -149,18 +151,11 @@
if (!eof) {
parseMethodTypeSignature(rawExceptionTypes);
} else {
- if(genericDecl instanceof Method) {
- Method m = (Method) genericDecl;
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = new ListOfTypes(m.getParameterTypes());
- this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
- this.returnType = m.getReturnType();
- } else {
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = ListOfTypes.EMPTY;
- this.exceptionTypes = ListOfTypes.EMPTY;
- this.returnType = void.class;
- }
+ Method m = (Method) genericDecl;
+ this.formalTypeParameters = ListOfVariables.EMPTY;
+ this.parameterTypes = new ListOfTypes(m.getParameterTypes());
+ this.exceptionTypes = new ListOfTypes(m.getExceptionTypes());
+ this.returnType = m.getReturnType();
}
}
@@ -177,16 +172,10 @@
if (!eof) {
parseMethodTypeSignature(rawExceptionTypes);
} else {
- if(genericDecl instanceof Constructor) {
- Constructor c = (Constructor) genericDecl;
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = new ListOfTypes(c.getParameterTypes());
- this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
- } else {
- this.formalTypeParameters = ListOfVariables.EMPTY;
- this.parameterTypes = ListOfTypes.EMPTY;
- this.exceptionTypes = ListOfTypes.EMPTY;
- }
+ Constructor c = (Constructor) genericDecl;
+ this.formalTypeParameters = ListOfVariables.EMPTY;
+ this.parameterTypes = new ListOfTypes(c.getParameterTypes());
+ this.exceptionTypes = new ListOfTypes(c.getExceptionTypes());
}
}
@@ -243,7 +232,7 @@
this.formalTypeParameters = typeParams.getArray();
}
- ImplForVariable<GenericDeclaration> parseFormalTypeParameter() {
+ TypeVariableImpl<GenericDeclaration> parseFormalTypeParameter() {
// FormalTypeParameter ::= Ident ClassBound {InterfaceBound}.
scanIdentifier();
@@ -263,7 +252,7 @@
bounds.add(parseFieldTypeSignature());
}
- return new ImplForVariable<GenericDeclaration>(genericDecl, name, bounds);
+ return new TypeVariableImpl<GenericDeclaration>(genericDecl, name, bounds);
}
Type parseFieldTypeSignature() {
@@ -276,7 +265,7 @@
case '[':
// ArrayTypeSignature ::= "[" TypSignature.
scanSymbol();
- return new ImplForArray(parseTypeSignature());
+ return new GenericArrayTypeImpl(parseTypeSignature());
case 'T':
return parseTypeVariableSignature();
default:
@@ -301,9 +290,9 @@
qualIdent.append(this.identifier);
ListOfTypes typeArgs = parseOptTypeArguments();
- ImplForType parentType =
- new ImplForType(null, qualIdent.toString(), typeArgs, loader);
- ImplForType type = parentType;
+ ParameterizedTypeImpl parentType =
+ new ParameterizedTypeImpl(null, qualIdent.toString(), typeArgs, loader);
+ ParameterizedTypeImpl type = parentType;
while (symbol == '.') {
// Deal with Member Classes:
@@ -311,7 +300,7 @@
scanIdentifier();
qualIdent.append("$").append(identifier); // FIXME: is "$" correct?
typeArgs = parseOptTypeArguments();
- type = new ImplForType(parentType, qualIdent.toString(), typeArgs,
+ type = new ParameterizedTypeImpl(parentType, qualIdent.toString(), typeArgs,
loader);
}
@@ -343,32 +332,32 @@
if (symbol == '*') {
scanSymbol();
extendsBound.add(Object.class);
- return new ImplForWildcard(extendsBound, superBound);
+ return new WildcardTypeImpl(extendsBound, superBound);
}
else if (symbol == '+') {
scanSymbol();
extendsBound.add(parseFieldTypeSignature());
- return new ImplForWildcard(extendsBound, superBound);
+ return new WildcardTypeImpl(extendsBound, superBound);
}
else if (symbol == '-') {
scanSymbol();
superBound.add(parseFieldTypeSignature());
extendsBound.add(Object.class);
- return new ImplForWildcard(extendsBound, superBound);
+ return new WildcardTypeImpl(extendsBound, superBound);
}
else {
return parseFieldTypeSignature();
}
}
- ImplForVariable<GenericDeclaration> parseTypeVariableSignature() {
+ TypeVariableImpl<GenericDeclaration> parseTypeVariableSignature() {
// TypeVariableSignature ::= "T" Ident ";".
expect('T');
scanIdentifier();
expect(';');
// Reference to type variable:
// Note: we don't know the declaring GenericDeclaration yet.
- return new ImplForVariable<GenericDeclaration>(genericDecl, identifier);
+ return new TypeVariableImpl<GenericDeclaration>(genericDecl, identifier);
}
Type parseTypeSignature() {
@@ -504,5 +493,4 @@
throw new GenericSignatureFormatError();
}
}
-
}
diff --git a/luni/src/main/java/libcore/reflect/InternalNames.java b/luni/src/main/java/libcore/reflect/InternalNames.java
new file mode 100644
index 0000000..b9e65cb
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/InternalNames.java
@@ -0,0 +1,87 @@
+/*
+ * 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 libcore.reflect;
+
+import java.lang.reflect.Array;
+
+/**
+ * Work with a type's internal name like "V" or "Ljava/lang/String;".
+ */
+public final class InternalNames {
+ private InternalNames() {
+ }
+
+ public static Class<?> getClass(ClassLoader classLoader, String internalName) {
+ if (internalName.startsWith("[")) {
+ Class<?> componentClass = getClass(classLoader, internalName.substring(1));
+ return Array.newInstance(componentClass, 0).getClass();
+ } else if (internalName.equals("Z")) {
+ return boolean.class;
+ } else if (internalName.equals("B")) {
+ return byte.class;
+ } else if (internalName.equals("S")) {
+ return short.class;
+ } else if (internalName.equals("I")) {
+ return int.class;
+ } else if (internalName.equals("J")) {
+ return long.class;
+ } else if (internalName.equals("F")) {
+ return float.class;
+ } else if (internalName.equals("D")) {
+ return double.class;
+ } else if (internalName.equals("C")) {
+ return char.class;
+ } else if (internalName.equals("V")) {
+ return void.class;
+ } else {
+ String name = internalName.substring(1, internalName.length() - 1).replace('/', '.');
+ try {
+ return classLoader.loadClass(name);
+ } catch (ClassNotFoundException e) {
+ NoClassDefFoundError error = new NoClassDefFoundError(name);
+ error.initCause(e);
+ throw error;
+ }
+ }
+ }
+
+ public static String getInternalName(Class<?> c) {
+ if (c.isArray()) {
+ return '[' + getInternalName(c.getComponentType());
+ } else if (c == boolean.class) {
+ return "Z";
+ } else if (c == byte.class) {
+ return "B";
+ } else if (c == short.class) {
+ return "S";
+ } else if (c == int.class) {
+ return "I";
+ } else if (c == long.class) {
+ return "J";
+ } else if (c == float.class) {
+ return "F";
+ } else if (c == double.class) {
+ return "D";
+ } else if (c == char.class) {
+ return "C";
+ } else if (c == void.class) {
+ return "V";
+ } else {
+ return 'L' + c.getName().replace('.', '/') + ';';
+ }
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java b/luni/src/main/java/libcore/reflect/ListOfTypes.java
similarity index 94%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java
rename to luni/src/main/java/libcore/reflect/ListOfTypes.java
index 59470f52..c5d90e2 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfTypes.java
+++ b/luni/src/main/java/libcore/reflect/ListOfTypes.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.Type;
import java.util.ArrayList;
@@ -58,7 +58,7 @@
for (int i = 0; i < unresolved.size(); i++) {
Type type = unresolved.get(i);
try {
- result[i] = ((ImplForType) type).getResolvedType();
+ result[i] = ((ParameterizedTypeImpl) type).getResolvedType();
} catch (ClassCastException e) {
result[i] = type;
}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java b/luni/src/main/java/libcore/reflect/ListOfVariables.java
similarity index 80%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java
rename to luni/src/main/java/libcore/reflect/ListOfVariables.java
index 0e757ac..5d96817 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ListOfVariables.java
+++ b/luni/src/main/java/libcore/reflect/ListOfVariables.java
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
-class ListOfVariables {
- public static final TypeVariable[] EMPTY = new ImplForVariable[0];
+final class ListOfVariables {
+ public static final TypeVariable[] EMPTY = new TypeVariableImpl[0];
- ArrayList<TypeVariable<?>> array = new ArrayList<TypeVariable<?>>();
+ final ArrayList<TypeVariable<?>> array = new ArrayList<TypeVariable<?>>();
void add (TypeVariable<?> elem) {
array.add(elem);
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
similarity index 89%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java
rename to luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
index b1f05d4..99dfe8b 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForType.java
+++ b/luni/src/main/java/libcore/reflect/ParameterizedTypeImpl.java
@@ -14,21 +14,20 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
-public final class ImplForType implements ParameterizedType {
+public final class ParameterizedTypeImpl implements ParameterizedType {
private final ListOfTypes args;
- private final ImplForType ownerType0; // Potentially unresolved.
+ private final ParameterizedTypeImpl ownerType0; // Potentially unresolved.
private Type ownerTypeRes;
private Class rawType; // Already resolved.
private final String rawTypeName;
private ClassLoader loader;
-
- public ImplForType(ImplForType ownerType, String rawTypeName,
+ public ParameterizedTypeImpl(ParameterizedTypeImpl ownerType, String rawTypeName,
ListOfTypes args, ClassLoader loader) {
this.ownerType0 = ownerType;
this.rawTypeName = rawTypeName;
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
similarity index 87%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java
rename to luni/src/main/java/libcore/reflect/TypeVariableImpl.java
index 783d223..2eb9827 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForVariable.java
+++ b/luni/src/main/java/libcore/reflect/TypeVariableImpl.java
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
+import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Method;
@@ -23,8 +24,8 @@
import java.lang.reflect.TypeVariable;
-public final class ImplForVariable<D extends GenericDeclaration> implements TypeVariable<D> {
- private ImplForVariable<D> formalVar;
+public final class TypeVariableImpl<D extends GenericDeclaration> implements TypeVariable<D> {
+ private TypeVariableImpl<D> formalVar;
private final GenericDeclaration declOfVarUser;
private final String name;
private D genericDeclaration;
@@ -51,7 +52,7 @@
* @param name type variable name
* @param bounds class and interface bounds
*/
- ImplForVariable(D genericDecl, String name, ListOfTypes bounds) {
+ TypeVariableImpl(D genericDecl, String name, ListOfTypes bounds) {
this.genericDeclaration = genericDecl;
this.name = name;
this.bounds = bounds;
@@ -63,7 +64,7 @@
* @param genericDecl declaration where a type variable is used
* @param name type variable name
*/
- ImplForVariable(D genericDecl, String name) {
+ TypeVariableImpl(D genericDecl, String name) {
this.name = name;
this.declOfVarUser = genericDecl;
}
@@ -83,11 +84,7 @@
if (decl instanceof Class) {
// FIXME: Is the following hierarchy correct?:
Class cl = (Class)decl;
- decl = cl.getEnclosingMethod();
- if (decl != null) {
- return decl;
- }
- decl = cl.getEnclosingConstructor();
+ decl = (GenericDeclaration) AnnotationAccess.getEnclosingMethodOrConstructor(cl);
if (decl != null) {
return decl;
}
@@ -113,7 +110,7 @@
throw new AssertionError("illegal type variable reference");
}
}
- formalVar = (ImplForVariable<D>) var;
+ formalVar = (TypeVariableImpl<D>) var;
this.genericDeclaration = formalVar.genericDeclaration;
this.bounds = formalVar.bounds;
}
diff --git a/luni/src/main/java/libcore/reflect/Types.java b/luni/src/main/java/libcore/reflect/Types.java
new file mode 100644
index 0000000..2132b11
--- /dev/null
+++ b/luni/src/main/java/libcore/reflect/Types.java
@@ -0,0 +1,167 @@
+/*
+ * 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 libcore.reflect;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class Types {
+ private Types() {
+ }
+
+ // Holds a mapping from Java type names to native type codes.
+ private static final Map<Class<?>, String> PRIMITIVE_TO_SIGNATURE;
+ static {
+ PRIMITIVE_TO_SIGNATURE = new HashMap<Class<?>, String>(9);
+ PRIMITIVE_TO_SIGNATURE.put(byte.class, "B");
+ PRIMITIVE_TO_SIGNATURE.put(char.class, "C");
+ PRIMITIVE_TO_SIGNATURE.put(short.class, "S");
+ PRIMITIVE_TO_SIGNATURE.put(int.class, "I");
+ PRIMITIVE_TO_SIGNATURE.put(long.class, "J");
+ PRIMITIVE_TO_SIGNATURE.put(float.class, "F");
+ PRIMITIVE_TO_SIGNATURE.put(double.class, "D");
+ PRIMITIVE_TO_SIGNATURE.put(void.class, "V");
+ PRIMITIVE_TO_SIGNATURE.put(boolean.class, "Z");
+ }
+
+ public static Type[] getClonedTypeArray(ListOfTypes types) {
+ return types.getResolvedTypes().clone();
+ }
+
+ public static Type getType(Type type) {
+ if (type instanceof ParameterizedTypeImpl) {
+ return ((ParameterizedTypeImpl)type).getResolvedType();
+ } else {
+ return type;
+ }
+ }
+
+ /**
+ * Returns the internal name of {@code clazz} (also known as the descriptor).
+ */
+ public static String getSignature(Class<?> clazz) {
+ String primitiveSignature = PRIMITIVE_TO_SIGNATURE.get(clazz);
+ if (primitiveSignature != null) {
+ return primitiveSignature;
+ } else if (clazz.isArray()) {
+ return "[" + getSignature(clazz.getComponentType());
+ } else {
+ // TODO: this separates packages with '.' rather than '/'
+ return "L" + clazz.getName() + ";";
+ }
+ }
+
+ /**
+ * Returns the names of {@code types} separated by commas.
+ */
+ public static String toString(Class<?>[] types) {
+ if (types.length == 0) {
+ return "";
+ }
+ StringBuilder result = new StringBuilder();
+ appendTypeName(result, types[0]);
+ for (int i = 1; i < types.length; i++) {
+ result.append(',');
+ appendTypeName(result, types[i]);
+ }
+ return result.toString();
+ }
+
+ /**
+ * Appends the best {@link #toString} name for {@code c} to {@code out}.
+ * This works around the fact that {@link Class#getName} is lousy for
+ * primitive arrays (it writes "[C" instead of "char[]") and {@link
+ * Class#getCanonicalName()} is lousy for nested classes (it uses a "."
+ * separator rather than a "$" separator).
+ */
+ public static void appendTypeName(StringBuilder out, Class<?> c) {
+ int dimensions = 0;
+ while (c.isArray()) {
+ c = c.getComponentType();
+ dimensions++;
+ }
+ out.append(c.getName());
+ for (int d = 0; d < dimensions; d++) {
+ out.append("[]");
+ }
+ }
+
+ /**
+ * Appends names of the {@code types} to {@code out} separated by commas.
+ */
+ public static void appendArrayGenericType(StringBuilder out, Type[] types) {
+ if (types.length == 0) {
+ return;
+ }
+ appendGenericType(out, types[0]);
+ for (int i = 1; i < types.length; i++) {
+ out.append(',');
+ appendGenericType(out, types[i]);
+ }
+ }
+
+ public static void appendGenericType(StringBuilder out, Type type) {
+ if (type instanceof TypeVariable) {
+ out.append(((TypeVariable) type).getName());
+ } else if (type instanceof ParameterizedType) {
+ out.append(type.toString());
+ } else if (type instanceof GenericArrayType) {
+ Type simplified = ((GenericArrayType) type).getGenericComponentType();
+ appendGenericType(out, simplified);
+ out.append("[]");
+ } else if (type instanceof Class) {
+ Class c = (Class<?>) type;
+ if (c.isArray()){
+ String as[] = c.getName().split("\\[");
+ int len = as.length-1;
+ if (as[len].length() > 1){
+ out.append(as[len].substring(1, as[len].length() - 1));
+ } else {
+ char ch = as[len].charAt(0);
+ if (ch == 'I') {
+ out.append("int");
+ } else if (ch == 'B') {
+ out.append("byte");
+ } else if (ch == 'J') {
+ out.append("long");
+ } else if (ch == 'F') {
+ out.append("float");
+ } else if (ch == 'D') {
+ out.append("double");
+ } else if (ch == 'S') {
+ out.append("short");
+ } else if (ch == 'C') {
+ out.append("char");
+ } else if (ch == 'Z') {
+ out.append("boolean");
+ } else if (ch == 'V') {
+ out.append("void");
+ }
+ }
+ for (int i = 0; i < len; i++){
+ out.append("[]");
+ }
+ } else {
+ out.append(c.getName());
+ }
+ }
+ }
+}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java b/luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
similarity index 91%
rename from luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
rename to luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
index b0605f2..97d2b26 100644
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/ImplForWildcard.java
+++ b/luni/src/main/java/libcore/reflect/WildcardTypeImpl.java
@@ -14,18 +14,18 @@
* limitations under the License.
*/
-package org.apache.harmony.luni.lang.reflect;
+package libcore.reflect;
import java.lang.reflect.MalformedParameterizedTypeException;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
-public final class ImplForWildcard implements WildcardType {
+public final class WildcardTypeImpl implements WildcardType {
private final ListOfTypes extendsBound, superBound;
- public ImplForWildcard(ListOfTypes extendsBound, ListOfTypes superBound) {
+ public WildcardTypeImpl(ListOfTypes extendsBound, ListOfTypes superBound) {
this.extendsBound = extendsBound;
this.superBound = superBound;
}
diff --git a/luni/src/main/java/libcore/util/ZoneInfoDB.java b/luni/src/main/java/libcore/util/ZoneInfoDB.java
index b211c93..10e3900 100644
--- a/luni/src/main/java/libcore/util/ZoneInfoDB.java
+++ b/luni/src/main/java/libcore/util/ZoneInfoDB.java
@@ -21,7 +21,7 @@
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel.MapMode;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -31,9 +31,6 @@
import libcore.io.IoUtils;
import libcore.io.MemoryMappedFile;
-// TODO: repackage this class, used by frameworks/base.
-import org.apache.harmony.luni.internal.util.TimezoneGetter;
-
/**
* A class used to initialize the time zone database. This implementation uses the
* Olson tzdata as the source of time zone information. However, to conserve
@@ -43,185 +40,190 @@
* @hide - used to implement TimeZone
*/
public final class ZoneInfoDB {
- private static final Object LOCK = new Object();
+ private static final TzData DATA =
+ new TzData(System.getenv("ANDROID_DATA") + "/misc/zoneinfo/tzdata",
+ System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/tzdata");
+ public static class TzData {
/**
* Rather than open, read, and close the big data file each time we look up a time zone,
* we map the big data file during startup, and then just use the MemoryMappedFile.
*
* At the moment, this "big" data file is about 500 KiB. At some point, that will be small
- * enough that we'll just keep the byte[] in memory.
+ * enough that we could just keep the byte[] in memory, but using mmap(2) like this has the
+ * nice property that even if someone replaces the file under us (because multiple gservices
+ * updates have gone out, say), we still get a consistent (if outdated) view of the world.
*/
- private static final MemoryMappedFile TZDATA = mapData();
+ private MemoryMappedFile mappedFile;
- private static String version;
- private static String zoneTab;
+ private String version;
+ private String zoneTab;
/**
* The 'ids' array contains time zone ids sorted alphabetically, for binary searching.
* The other two arrays are in the same order. 'byteOffsets' gives the byte offset
* of each time zone, and 'rawUtcOffsets' gives the time zone's raw UTC offset.
*/
- private static String[] ids;
- private static int[] byteOffsets;
- private static int[] rawUtcOffsets;
+ private String[] ids;
+ private int[] byteOffsets;
+ private int[] rawUtcOffsets;
- static {
+ public TzData(String... paths) {
+ for (String path : paths) {
+ if (loadData(path)) {
+ return;
+ }
+ }
+
+ // We didn't find any usable tzdata on disk, so let's just hard-code knowledge of "GMT".
+ // This is actually implemented in TimeZone itself, so if this is the only time zone
+ // we report, we won't be asked any more questions.
+ System.logE("Couldn't find any tzdata!");
+ version = "missing";
+ zoneTab = "# Emergency fallback data.\n";
+ ids = new String[] { "GMT" };
+ byteOffsets = rawUtcOffsets = new int[1];
+ }
+
+ private boolean loadData(String path) {
+ try {
+ mappedFile = MemoryMappedFile.mmapRO(path);
+ } catch (ErrnoException errnoException) {
+ return false;
+ }
+ try {
readHeader();
+ return true;
+ } catch (Exception ex) {
+ // Something's wrong with the file.
+ // Log the problem and return false so we try the next choice.
+ System.logE("tzdata file \"" + path + "\" was present but invalid!", ex);
+ return false;
+ }
}
- private ZoneInfoDB() {
+ private void readHeader() {
+ // byte[12] tzdata_version -- "tzdata2012f\0"
+ // int index_offset
+ // int data_offset
+ // int zonetab_offset
+ BufferIterator it = mappedFile.bigEndianIterator();
+
+ byte[] tzdata_version = new byte[12];
+ it.readByteArray(tzdata_version, 0, tzdata_version.length);
+ String magic = new String(tzdata_version, 0, 6, StandardCharsets.US_ASCII);
+ if (!magic.equals("tzdata") || tzdata_version[11] != 0) {
+ throw new RuntimeException("bad tzdata magic: " + Arrays.toString(tzdata_version));
+ }
+ version = new String(tzdata_version, 6, 5, StandardCharsets.US_ASCII);
+
+ int index_offset = it.readInt();
+ int data_offset = it.readInt();
+ int zonetab_offset = it.readInt();
+
+ readIndex(it, index_offset, data_offset);
+ readZoneTab(it, zonetab_offset, (int) mappedFile.size() - zonetab_offset);
}
- private static void readHeader() {
- // byte[12] tzdata_version -- "tzdata2012f\0"
- // int index_offset
- // int data_offset
- // int zonetab_offset
- BufferIterator it = TZDATA.bigEndianIterator();
+ private void readZoneTab(BufferIterator it, int zoneTabOffset, int zoneTabSize) {
+ byte[] bytes = new byte[zoneTabSize];
+ it.seek(zoneTabOffset);
+ it.readByteArray(bytes, 0, bytes.length);
+ zoneTab = new String(bytes, 0, bytes.length, StandardCharsets.US_ASCII);
+ }
- byte[] tzdata_version = new byte[12];
- it.readByteArray(tzdata_version, 0, tzdata_version.length);
- String magic = new String(tzdata_version, 0, 6, Charsets.US_ASCII);
- if (!magic.equals("tzdata") || tzdata_version[11] != 0) {
- throw new RuntimeException("bad tzdata magic: " + Arrays.toString(tzdata_version));
+ private void readIndex(BufferIterator it, int indexOffset, int dataOffset) {
+ it.seek(indexOffset);
+
+ // The database reserves 40 bytes for each id.
+ final int SIZEOF_TZNAME = 40;
+ // The database uses 32-bit (4 byte) integers.
+ final int SIZEOF_TZINT = 4;
+
+ byte[] idBytes = new byte[SIZEOF_TZNAME];
+ int indexSize = (dataOffset - indexOffset);
+ int entryCount = indexSize / (SIZEOF_TZNAME + 3*SIZEOF_TZINT);
+
+ char[] idChars = new char[entryCount * SIZEOF_TZNAME];
+ int[] idEnd = new int[entryCount];
+ int idOffset = 0;
+
+ byteOffsets = new int[entryCount];
+ rawUtcOffsets = new int[entryCount];
+
+ for (int i = 0; i < entryCount; i++) {
+ it.readByteArray(idBytes, 0, idBytes.length);
+
+ byteOffsets[i] = it.readInt();
+ byteOffsets[i] += dataOffset; // TODO: change the file format so this is included.
+
+ int length = it.readInt();
+ if (length < 44) {
+ throw new AssertionError("length in index file < sizeof(tzhead)");
}
- version = new String(tzdata_version, 6, 5, Charsets.US_ASCII);
+ rawUtcOffsets[i] = it.readInt();
- int index_offset = it.readInt();
- int data_offset = it.readInt();
- int zonetab_offset = it.readInt();
-
- readIndex(it, index_offset, data_offset);
- readZoneTab(it, zonetab_offset);
- }
-
- private static MemoryMappedFile mapData() {
- MemoryMappedFile result = mapData(System.getenv("ANDROID_DATA") + "/misc/zoneinfo/");
- if (result == null) {
- result = mapData(System.getenv("ANDROID_ROOT") + "/usr/share/zoneinfo/");
- if (result == null) {
- throw new AssertionError("Couldn't find any tzdata!");
- }
- }
- return result;
- }
-
- private static MemoryMappedFile mapData(String directory) {
- try {
- return MemoryMappedFile.mmapRO(directory + "tzdata");
- } catch (ErrnoException errnoException) {
- return null;
- }
- }
-
- private static void readZoneTab(BufferIterator it, int zoneTabOffset) {
- byte[] bytes = new byte[(int) TZDATA.size() - zoneTabOffset];
- it.seek(zoneTabOffset);
- it.readByteArray(bytes, 0, bytes.length);
- zoneTab = new String(bytes, 0, bytes.length, Charsets.US_ASCII);
- }
-
- private static void readIndex(BufferIterator it, int indexOffset, int dataOffset) {
- it.seek(indexOffset);
-
- // The database reserves 40 bytes for each id.
- final int SIZEOF_TZNAME = 40;
- // The database uses 32-bit (4 byte) integers.
- final int SIZEOF_TZINT = 4;
-
- byte[] idBytes = new byte[SIZEOF_TZNAME];
- int indexSize = (dataOffset - indexOffset);
- int entryCount = indexSize / (SIZEOF_TZNAME + 3*SIZEOF_TZINT);
-
- char[] idChars = new char[entryCount * SIZEOF_TZNAME];
- int[] idEnd = new int[entryCount];
- int idOffset = 0;
-
- byteOffsets = new int[entryCount];
- rawUtcOffsets = new int[entryCount];
-
- for (int i = 0; i < entryCount; i++) {
- it.readByteArray(idBytes, 0, idBytes.length);
-
- byteOffsets[i] = it.readInt();
- byteOffsets[i] += dataOffset; // TODO: change the file format so this is included.
-
- int length = it.readInt();
- if (length < 44) {
- throw new AssertionError("length in index file < sizeof(tzhead)");
- }
- rawUtcOffsets[i] = it.readInt();
-
- // Don't include null chars in the String
- int len = idBytes.length;
- for (int j = 0; j < len; j++) {
- if (idBytes[j] == 0) {
- break;
- }
- idChars[idOffset++] = (char) (idBytes[j] & 0xFF);
- }
-
- idEnd[i] = idOffset;
+ // Don't include null chars in the String
+ int len = idBytes.length;
+ for (int j = 0; j < len; j++) {
+ if (idBytes[j] == 0) {
+ break;
+ }
+ idChars[idOffset++] = (char) (idBytes[j] & 0xFF);
}
- // We create one string containing all the ids, and then break that into substrings.
- // This way, all ids share a single char[] on the heap.
- String allIds = new String(idChars, 0, idOffset);
- ids = new String[entryCount];
- for (int i = 0; i < entryCount; i++) {
- ids[i] = allIds.substring(i == 0 ? 0 : idEnd[i - 1], idEnd[i]);
+ idEnd[i] = idOffset;
+ }
+
+ // We create one string containing all the ids, and then break that into substrings.
+ // This way, all ids share a single char[] on the heap.
+ String allIds = new String(idChars, 0, idOffset);
+ ids = new String[entryCount];
+ for (int i = 0; i < entryCount; i++) {
+ ids[i] = allIds.substring(i == 0 ? 0 : idEnd[i - 1], idEnd[i]);
+ }
+ }
+
+ public String[] getAvailableIDs() {
+ return ids.clone();
+ }
+
+ public String[] getAvailableIDs(int rawOffset) {
+ List<String> matches = new ArrayList<String>();
+ for (int i = 0, end = rawUtcOffsets.length; i < end; ++i) {
+ if (rawUtcOffsets[i] == rawOffset) {
+ matches.add(ids[i]);
}
+ }
+ return matches.toArray(new String[matches.size()]);
}
- public static TimeZone makeTimeZone(String id) throws IOException {
- // Work out where in the big data file this time zone is.
- int index = Arrays.binarySearch(ids, id);
- if (index < 0) {
- return null;
- }
-
- BufferIterator it = TZDATA.bigEndianIterator();
- it.skip(byteOffsets[index]);
-
- return ZoneInfo.makeTimeZone(id, it);
+ public String getVersion() {
+ return version;
}
- public static String[] getAvailableIDs() {
- return ids.clone();
+ public String getZoneTab() {
+ return zoneTab;
}
- public static String[] getAvailableIDs(int rawOffset) {
- List<String> matches = new ArrayList<String>();
- for (int i = 0, end = rawUtcOffsets.length; i < end; ++i) {
- if (rawUtcOffsets[i] == rawOffset) {
- matches.add(ids[i]);
- }
- }
- return matches.toArray(new String[matches.size()]);
- }
+ public TimeZone makeTimeZone(String id) throws IOException {
+ // Work out where in the big data file this time zone is.
+ int index = Arrays.binarySearch(ids, id);
+ if (index < 0) {
+ return null;
+ }
- public static TimeZone getSystemDefault() {
- synchronized (LOCK) {
- TimezoneGetter tzGetter = TimezoneGetter.getInstance();
- String zoneName = tzGetter != null ? tzGetter.getId() : null;
- if (zoneName != null) {
- zoneName = zoneName.trim();
- }
- if (zoneName == null || zoneName.isEmpty()) {
- // use localtime for the simulator
- // TODO: what does that correspond to?
- zoneName = "localtime";
- }
- return TimeZone.getTimeZone(zoneName);
- }
- }
+ BufferIterator it = mappedFile.bigEndianIterator();
+ it.skip(byteOffsets[index]);
- public static String getVersion() {
- return version;
+ return ZoneInfo.makeTimeZone(id, it);
}
+ }
- public static String getZoneTab() {
- return zoneTab;
- }
+ private ZoneInfoDB() {
+ }
+
+ public static TzData getInstance() {
+ return DATA;
+ }
}
diff --git a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java b/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java
deleted file mode 100644
index bd700fc..0000000
--- a/luni/src/main/java/org/apache/harmony/luni/lang/reflect/Types.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 org.apache.harmony.luni.lang.reflect;
-
-import java.lang.reflect.Type;
-
-public class Types {
-
- public static Type[] getClonedTypeArray(ListOfTypes types) {
- return types.getResolvedTypes().clone();
- }
-
- public static Type getType(Type type) {
- if (type instanceof ImplForType) {
- return ((ImplForType)type).getResolvedType();
- } else {
- return type;
- }
- }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
index 64d7ced..26097cf 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1GeneralizedTime.java
@@ -23,7 +23,7 @@
package org.apache.harmony.security.asn1;
import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
@@ -99,7 +99,7 @@
temp = temp.substring(0, currLength);
}
- out.content = (temp + "Z").getBytes(Charsets.UTF_8);
+ out.content = (temp + "Z").getBytes(StandardCharsets.UTF_8);
out.length = ((byte[]) out.content).length;
}
}
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
index 024b65f..f7ea2bd 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1StringType.java
@@ -23,7 +23,7 @@
package org.apache.harmony.security.asn1;
import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
/**
* This class is the super class for all string ASN.1 types
@@ -39,12 +39,12 @@
@Override
public Object getDecodedObject(BerInputStream in) throws IOException {
- return new String(in.buffer, in.contentOffset, in.length, Charsets.UTF_8);
+ return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.UTF_8);
}
@Override
public void setEncodingContent(BerOutputStream out) {
- byte[] bytes = ((String) out.content).getBytes(Charsets.UTF_8);
+ byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
out.content = bytes;
out.length = bytes.length;
}
@@ -96,7 +96,7 @@
public Object getDecodedObject(BerInputStream in) throws IOException {
/* To ensure we get the correct encoding on non-ASCII platforms, specify
that we wish to convert from ASCII to the default platform encoding */
- return new String(in.buffer, in.contentOffset, in.length, Charsets.ISO_8859_1);
+ return new String(in.buffer, in.contentOffset, in.length, StandardCharsets.ISO_8859_1);
}
public void encodeASN(BerOutputStream out) {
@@ -109,7 +109,7 @@
}
public void setEncodingContent(BerOutputStream out) {
- byte[] bytes = ((String) out.content).getBytes(Charsets.UTF_8);
+ byte[] bytes = ((String) out.content).getBytes(StandardCharsets.UTF_8);
out.content = bytes;
out.length = bytes.length;
}
diff --git a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
index 7c355f8..a3e77d3 100644
--- a/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
+++ b/luni/src/main/java/org/apache/harmony/security/asn1/ASN1UTCTime.java
@@ -23,7 +23,7 @@
package org.apache.harmony.security.asn1;
import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
@@ -97,7 +97,7 @@
@Override public void setEncodingContent(BerOutputStream out) {
SimpleDateFormat sdf = new SimpleDateFormat(UTC_PATTERN, Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
- out.content = sdf.format(out.content).getBytes(Charsets.UTF_8);
+ out.content = sdf.format(out.content).getBytes(StandardCharsets.UTF_8);
out.length = ((byte[]) out.content).length;
}
}
diff --git a/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java b/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
index 4015e70..65782b2 100644
--- a/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
+++ b/luni/src/main/java/org/apache/harmony/security/pkcs7/SignerInfo.java
@@ -112,11 +112,16 @@
return authenticatedAttributes.getAttributes();
}
+ /**
+ * Returns the non-IMPLICIT ASN.1 encoding of the "authAttrs" from this
+ * SignerInfo. That is, it will return as the encoding of a generic ASN.1
+ * SET.
+ */
public byte[] getEncodedAuthenticatedAttributes() {
if (authenticatedAttributes == null) {
return null;
}
- return authenticatedAttributes.getEncoded();
+ return AuthenticatedAttributes.ASN1.encode(authenticatedAttributes.getAttributes());
}
public byte[] getEncryptedDigest() {
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
index 9453164..9129ec2 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertFactoryImpl.java
@@ -24,7 +24,7 @@
import java.io.IOException;
import java.io.InputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.CertPath;
@@ -432,8 +432,8 @@
// ------------------------ Staff methods ------------------------------
// ---------------------------------------------------------------------
- private static final byte[] PEM_BEGIN = "-----BEGIN".getBytes(Charsets.UTF_8);
- private static final byte[] PEM_END = "-----END".getBytes(Charsets.UTF_8);
+ private static final byte[] PEM_BEGIN = "-----BEGIN".getBytes(StandardCharsets.UTF_8);
+ private static final byte[] PEM_END = "-----END".getBytes(StandardCharsets.UTF_8);
/**
* Code describing free format for PEM boundary suffix:
* "^-----BEGIN.*\n" at the beginning, and<br>
@@ -445,7 +445,7 @@
* "^-----BEGIN CERTIFICATE-----\n" at the beginning, and<br>
* "\n-----END CERTIFICATE-----" at the end.
*/
- private static final byte[] CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes(Charsets.UTF_8);
+ private static final byte[] CERT_BOUND_SUFFIX = " CERTIFICATE-----".getBytes(StandardCharsets.UTF_8);
/**
* Method retrieves the PEM encoded data from the stream
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
index 68bcec6..4600bdc 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/cert/X509CertImpl.java
@@ -48,7 +48,6 @@
import org.apache.harmony.security.x509.Extension;
import org.apache.harmony.security.x509.Extensions;
import org.apache.harmony.security.x509.TBSCertificate;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
/**
* This class is an implementation of X509Certificate. It wraps
@@ -67,11 +66,11 @@
/** the core object to be wrapped in X509Certificate */
private final Certificate certificate;
+ private final TBSCertificate tbsCert;
+ private final Extensions extensions;
// to speed up access to the info, the following fields
// cache values retrieved from the certificate object,
// initialized using the "single-check idiom".
- private final TBSCertificate tbsCert;
- private final Extensions extensions;
private volatile long notBefore = -1;
private volatile long notAfter = -1;
private volatile BigInteger serialNumber;
@@ -369,12 +368,7 @@
throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException {
- Signature signature;
- try {
- signature = Signature.getInstance(getSigAlgName(), OpenSSLProvider.PROVIDER_NAME);
- } catch (NoSuchAlgorithmException ignored) {
- signature = Signature.getInstance(getSigAlgName());
- }
+ Signature signature = Signature.getInstance(getSigAlgName());
signature.initVerify(key);
// retrieve the encoding of the TBSCertificate structure
byte[] tbsCertificateLocal = getTbsCertificateInternal();
@@ -389,16 +383,7 @@
throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
NoSuchProviderException, SignatureException {
- Signature signature;
- try {
- if (sigProvider == null) {
- signature = Signature.getInstance(getSigAlgName(), OpenSSLProvider.PROVIDER_NAME);
- } else {
- signature = Signature.getInstance(getSigAlgName(), sigProvider);
- }
- } catch (NoSuchAlgorithmException ignored) {
- signature = Signature.getInstance(getSigAlgName(), sigProvider);
- }
+ Signature signature = Signature.getInstance(getSigAlgName(), sigProvider);
signature.initVerify(key);
// retrieve the encoding of the TBSCertificate structure
byte[] tbsCertificateLocal = getTbsCertificateInternal();
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
index 70a2449..7c2785a 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/CryptoProvider.java
@@ -55,10 +55,8 @@
put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
put("Alg.Alias.MessageDigest.SHA", "SHA-1");
- if (RandomBitsSupplier.isServiceAvailable()) {
- put("SecureRandom.SHA1PRNG", SR_NAME);
- put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
- }
+ put("SecureRandom.SHA1PRNG", SR_NAME);
+ put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
put("Signature.SHA1withDSA", SIGN_NAME);
put("Signature.SHA1withDSA ImplementedIn", "Software");
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
deleted file mode 100644
index ad3a280..0000000
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/RandomBitsSupplier.java
+++ /dev/null
@@ -1,56 +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.security.provider.crypto;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.ProviderException;
-import libcore.io.Streams;
-
-/**
- * Supplies random bits from /dev/urandom.
- */
-public class RandomBitsSupplier implements SHA1_Data {
- private static FileInputStream devURandom;
- static {
- try {
- devURandom = new FileInputStream(new File("/dev/urandom"));
- } catch (IOException ex) {
- throw new RuntimeException(ex);
- }
- }
-
- static boolean isServiceAvailable() {
- return (devURandom != null);
- }
-
- public static byte[] getRandomBits(int byteCount) {
- if (byteCount <= 0) {
- throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
- }
- try {
- byte[] result = new byte[byteCount];
- Streams.readFully(devURandom, result, 0, byteCount);
- return result;
- } catch (Exception ex) {
- throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
- }
- }
-}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
similarity index 80%
rename from luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
rename to luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
index b559576..fc6a847 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_Data.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Constants.java
@@ -28,56 +28,55 @@
* - a set of constant values, H0-H4, defined in "SECURE HASH STANDARD", FIPS PUB 180-2 ;<BR>
* - implementation constant values to use in classes using SHA-1 algorithm. <BR>
*/
+public final class SHA1Constants {
+ private SHA1Constants() {
+ }
-
-public interface SHA1_Data {
+ /**
+ * constant defined in "SECURE HASH STANDARD"
+ */
+ public static final int H0 = 0x67452301;
/**
* constant defined in "SECURE HASH STANDARD"
*/
- static final int H0 = 0x67452301;
+ public static final int H1 = 0xEFCDAB89;
/**
* constant defined in "SECURE HASH STANDARD"
*/
- static final int H1 = 0xEFCDAB89;
+ public static final int H2 = 0x98BADCFE;
/**
* constant defined in "SECURE HASH STANDARD"
*/
- static final int H2 = 0x98BADCFE;
+ public static final int H3 = 0x10325476;
/**
* constant defined in "SECURE HASH STANDARD"
*/
- static final int H3 = 0x10325476;
-
-
- /**
- * constant defined in "SECURE HASH STANDARD"
- */
- static final int H4 = 0xC3D2E1F0;
+ public static final int H4 = 0xC3D2E1F0;
/**
* offset in buffer to store number of bytes in 0-15 word frame
*/
- static final int BYTES_OFFSET = 81;
+ public static final int BYTES_OFFSET = 81;
/**
* offset in buffer to store current hash value
*/
- static final int HASH_OFFSET = 82;
+ public static final int HASH_OFFSET = 82;
/**
* # of bytes in H0-H4 words; <BR>
* in this implementation # is set to 20 (in general # varies from 1 to 20)
*/
- static final int DIGEST_LENGTH = 20;
+ public static final int DIGEST_LENGTH = 20;
}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
index d42b901..57b9005 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1Impl.java
@@ -22,6 +22,7 @@
package org.apache.harmony.security.provider.crypto;
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
/**
* This class contains methods providing SHA-1 functionality to use in classes. <BR>
@@ -48,9 +49,7 @@
* The resulting hash value replaces the previous hash value in the array;
* original bits of the message are not preserved.
*/
-
-
-public class SHA1Impl implements SHA1_Data {
+public class SHA1Impl {
/**
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
index 4d99d62..5c0e328 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1PRNG_SecureRandomImpl.java
@@ -18,29 +18,41 @@
package org.apache.harmony.security.provider.crypto;
+import dalvik.system.BlockGuard;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.security.InvalidParameterException;
+import java.security.ProviderException;
import java.security.SecureRandomSpi;
import libcore.io.Streams;
import libcore.util.EmptyArray;
-/**
- * This class extends the SecureRandomSpi class implementing all its abstract methods. <BR>
- * <BR>
- * To generate pseudo-random bits, the implementation uses technique described in
- * the "Random Number Generator (RNG) algorithms" section, Appendix A,
- * JavaTM Cryptography Architecture, API Specification&Reference <BR>
- * <BR>
- * The class implements the Serializable interface.
- */
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
-public class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable, SHA1_Data {
+/**
+ * This class extends the SecureRandomSpi class implementing all its abstract methods.
+ *
+ * <p>To generate pseudo-random bits, the implementation uses technique described in
+ * the "Random Number Generator (RNG) algorithms" section, Appendix A,
+ * JavaTM Cryptography Architecture, API Specification & Reference.
+ */
+public class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable {
private static final long serialVersionUID = 283736797212159675L;
+ private static FileInputStream devURandom;
+ static {
+ try {
+ devURandom = new FileInputStream(new File("/dev/urandom"));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
// constants to use in expressions operating on bytes in int and long variables:
// END_FLAGS - final bytes in words to append to message;
// see "ch.5.1 Padding the Message, FIPS 180-2"
@@ -241,7 +253,7 @@
if (myRandom == null) {
myRandom = new SHA1PRNG_SecureRandomImpl();
- myRandom.engineSetSeed(RandomBitsSupplier.getRandomBits(DIGEST_LENGTH));
+ myRandom.engineSetSeed(getRandomBytes(DIGEST_LENGTH));
}
myBytes = new byte[numBytes];
@@ -285,7 +297,7 @@
if (state == UNDEFINED) {
// no seed supplied by user, hence it is generated thus randomizing internal state
- updateSeed(RandomBitsSupplier.getRandomBits(DIGEST_LENGTH));
+ updateSeed(getRandomBytes(DIGEST_LENGTH));
nextBIndex = HASHBYTES_TO_USE;
// updateSeed(...) updates where the last word of the seed is, so we
@@ -531,4 +543,22 @@
nextBIndex = ois.readInt();
Streams.readFully(ois, nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
}
+
+ private static byte[] getRandomBytes(int byteCount) {
+ if (byteCount <= 0) {
+ throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
+ }
+
+ BlockGuard.Policy originalPolicy = BlockGuard.getThreadPolicy();
+ try {
+ BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
+ byte[] result = new byte[byteCount];
+ Streams.readFully(devURandom, result, 0, byteCount);
+ return result;
+ } catch (Exception ex) {
+ throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
+ } finally {
+ BlockGuard.setThreadPolicy(originalPolicy);
+ }
+ }
}
diff --git a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
index 71223b7..3f41f18 100644
--- a/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
+++ b/luni/src/main/java/org/apache/harmony/security/provider/crypto/SHA1_MessageDigestImpl.java
@@ -18,20 +18,18 @@
package org.apache.harmony.security.provider.crypto;
-
import java.security.DigestException;
import java.security.MessageDigestSpi;
import java.util.Arrays;
+import static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
/**
* This class extends the MessageDigestSpi class implementing all its abstract methods;
* it overrides the "Object clone()" and "int engineGetDigestLength()" methods. <BR>
* The class implements the Cloneable interface.
*/
-
-
-public class SHA1_MessageDigestImpl extends MessageDigestSpi implements Cloneable, SHA1_Data {
+public class SHA1_MessageDigestImpl extends MessageDigestSpi implements Cloneable {
private int[] buffer; // buffer has the following structure:
// - 0-16 - frame for accumulating a message
// - 17-79 - for SHA1Impl methods
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 465748e..9d01f8d 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,7 +30,6 @@
import java.util.Map.Entry;
import java.util.Set;
import org.apache.harmony.security.asn1.ObjectIdentifier;
-import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
/**
* Provides Algorithm Name to OID and OID to Algorithm Name mappings. Some known
@@ -114,12 +113,7 @@
*/
public static String map2OID(String algName) {
// alg2OidMap map contains upper case keys
- final String result = alg2OidMap.get(algName.toUpperCase(Locale.US));
- if (result != null) {
- return result;
- }
-
- return NativeCrypto.OBJ_txt2nid_oid(algName);
+ return alg2OidMap.get(algName.toUpperCase(Locale.US));
}
/**
@@ -130,14 +124,12 @@
*/
public static String map2AlgName(String oid) {
// oid2AlgMap map contains upper case values
- String algUC = oid2AlgMap.get(oid);
+ final String algUC = oid2AlgMap.get(oid);
// if not null there is always map UC->Orig
if (algUC != null) {
return algAliasesMap.get(algUC);
}
-
- // If we don't know about this OID, ask OpenSSL if it does.
- return NativeCrypto.OBJ_txt2nid_longName(oid);
+ return null;
}
/**
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index 6d86dc6..3fdd621 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -36,13 +36,14 @@
import java.util.LinkedList;
import java.util.List;
import javax.security.auth.x500.X500Principal;
+
+import org.apache.harmony.security.asn1.ASN1OctetString;
import org.apache.harmony.security.asn1.BerInputStream;
import org.apache.harmony.security.pkcs7.ContentInfo;
import org.apache.harmony.security.pkcs7.SignedData;
import org.apache.harmony.security.pkcs7.SignerInfo;
import org.apache.harmony.security.provider.cert.X509CertImpl;
import org.apache.harmony.security.x501.AttributeTypeAndValue;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
public class JarUtils {
@@ -193,15 +194,37 @@
byte[] existingDigest = null;
for (AttributeTypeAndValue a : atr) {
if (Arrays.equals(a.getType().getOid(), MESSAGE_DIGEST_OID)) {
-//TODO value existingDigest = a.AttributeValue;
+ if (existingDigest != null) {
+ throw new SecurityException("Too many MessageDigest attributes");
+ }
+ Collection<?> entries = a.getValue().getValues(ASN1OctetString.getInstance());
+ if (entries.size() != 1) {
+ throw new SecurityException("Too many values for MessageDigest attribute");
+ }
+ existingDigest = (byte[]) entries.iterator().next();
}
}
- if (existingDigest != null) {
- MessageDigest md = MessageDigest.getInstance(sigInfo.getDigestAlgorithm());
- byte[] computedDigest = md.digest(sfBytes);
- if (!Arrays.equals(existingDigest, computedDigest)) {
- throw new SecurityException("Incorrect MD");
- }
+
+ // RFC 3852 section 9.2: it authAttrs is present, it must have a
+ // message digest entry.
+ if (existingDigest == null) {
+ throw new SecurityException("Missing MessageDigest in Authenticated Attributes");
+ }
+
+ MessageDigest md = null;
+ if (daOid != null) {
+ md = MessageDigest.getInstance(daOid);
+ }
+ if (md == null && daName != null) {
+ md = MessageDigest.getInstance(daName);
+ }
+ if (md == null) {
+ return null;
+ }
+
+ byte[] computedDigest = md.digest(sfBytes);
+ if (!Arrays.equals(existingDigest, computedDigest)) {
+ throw new SecurityException("Incorrect MD");
}
}
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
index 89f5b3e..3b5f622 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeTypeAndValue.java
@@ -23,7 +23,7 @@
package org.apache.harmony.security.x501;
import java.io.IOException;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
@@ -68,7 +68,7 @@
= new ObjectIdentifier(new int[] { 2, 5, 4, 3 }, "CN", RFC1779_NAMES);
/** Domain component attribute (name from RFC 2253) */
- private static final ObjectIdentifier DC = new ObjectIdentifier(
+ public static final ObjectIdentifier DC = new ObjectIdentifier(
new int[] { 0, 9, 2342, 19200300, 100, 1, 25 }, "DC", RFC2253_NAMES);
/** DN qualifier attribute (name from API spec) */
@@ -79,7 +79,7 @@
= new ObjectIdentifier(new int[] { 2, 5, 4, 46 }, "DNQUALIFIER", RFC2459_NAMES);
/** Email Address attribute (name from API spec) */
- private static final ObjectIdentifier EMAILADDRESS = new ObjectIdentifier(
+ public static final ObjectIdentifier EMAILADDRESS = new ObjectIdentifier(
new int[] { 1, 2, 840, 113549, 1, 9, 1}, "EMAILADDRESS", RFC2459_NAMES);
/** Generation attribute (qualifies an individual's name) (name from API spec) */
@@ -179,6 +179,32 @@
KNOWN_NAMES.putAll(RFC2459_NAMES);
}
+ /**
+ * Parses OID string representation.
+ *
+ * @param sOid
+ * string representation of OID
+ *
+ * @throws IOException
+ * if OID can not be created from its string representation
+ */
+ public static ObjectIdentifier getObjectIdentifier(String sOid) throws IOException {
+ if (sOid.charAt(0) >= '0' && sOid.charAt(0) <= '9') {
+ int[] array = org.apache.harmony.security.asn1.ObjectIdentifier.toIntArray(sOid);
+ ObjectIdentifier thisOid = getOID(array);
+ if (thisOid == null) {
+ thisOid = new ObjectIdentifier(array);
+ }
+ return thisOid;
+
+ }
+ ObjectIdentifier thisOid = KNOWN_NAMES.get(sOid.toUpperCase(Locale.US));
+ if (thisOid == null) {
+ throw new IOException("Unrecognizable attribute name: " + sOid);
+ }
+ return thisOid;
+ }
+
/** Attribute type */
private final ObjectIdentifier oid;
@@ -196,31 +222,15 @@
}
/**
- * Creates AttributeTypeAndValue with OID and AttributeValue. Parses OID
- * string representation
+ * Creates AttributeTypeAndValue with OID and AttributeValue.
*
- * @param sOid
- * string representation of OID
+ * @param oid
+ * object identifier
* @param value
* attribute value
- * @throws IOException
- * if OID can not be created from its string representation
*/
- public AttributeTypeAndValue(String sOid, AttributeValue value) throws IOException {
- if (sOid.charAt(0) >= '0' && sOid.charAt(0) <= '9') {
- int[] array = org.apache.harmony.security.asn1.ObjectIdentifier.toIntArray(sOid);
- ObjectIdentifier thisOid = getOID(array);
- if (thisOid == null) {
- thisOid = new ObjectIdentifier(array);
- }
- this.oid = thisOid;
-
- } else {
- this.oid = KNOWN_NAMES.get(sOid.toUpperCase(Locale.US));
- if (this.oid == null) {
- throw new IOException("Unrecognizable attribute name: " + sOid);
- }
- }
+ public AttributeTypeAndValue(ObjectIdentifier oid, AttributeValue value) throws IOException {
+ this.oid = oid;
this.value = value;
}
@@ -291,6 +301,10 @@
return oid;
}
+ public AttributeValue getValue() {
+ return value;
+ }
+
/**
* According to RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt)
* X.501 AttributeTypeAndValue structure is defined as follows:
@@ -368,7 +382,7 @@
av.bytes = (byte[]) out.content;
out.content = av;
} else {
- av.bytes = av.rawString.getBytes(Charsets.UTF_8);
+ av.bytes = av.rawString.getBytes(StandardCharsets.UTF_8);
out.length = av.bytes.length;
}
}
diff --git a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
index 2369d0f..63be3f1 100644
--- a/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
+++ b/luni/src/main/java/org/apache/harmony/security/x501/AttributeValue.java
@@ -23,21 +23,25 @@
package org.apache.harmony.security.x501;
import java.io.IOException;
+import java.util.Collection;
+import org.apache.harmony.security.asn1.ASN1SetOf;
import org.apache.harmony.security.asn1.ASN1StringType;
+import org.apache.harmony.security.asn1.ASN1Type;
import org.apache.harmony.security.asn1.DerInputStream;
+import org.apache.harmony.security.utils.ObjectIdentifier;
/**
* X.501 Attribute Value
*/
public final class AttributeValue {
- public final boolean wasEncoded;
+ public boolean wasEncoded;
- public String escapedString;
+ public final String escapedString;
private String hexString;
- private int tag = -1;
+ private final int tag;
public byte[] encoded;
@@ -45,15 +49,26 @@
public boolean hasQE; // raw string contains '"' or '\'
- public String rawString;
+ public final String rawString;
- public AttributeValue(String parsedString, boolean hasQorE) {
+ public AttributeValue(String parsedString, boolean hasQorE, ObjectIdentifier oid) {
wasEncoded = false;
this.hasQE = hasQorE;
-
this.rawString = parsedString;
- this.escapedString = makeEscaped(rawString);
+ this.escapedString = makeEscaped(rawString); // overwrites hasQE
+
+ int tag;
+ if (oid == AttributeTypeAndValue.EMAILADDRESS || oid == AttributeTypeAndValue.DC) {
+ // http://www.rfc-editor.org/rfc/rfc5280.txt
+ // says that EmailAddress and DomainComponent should be a IA5String
+ tag = ASN1StringType.IA5STRING.id;
+ } else if (isPrintableString(rawString)) {
+ tag = ASN1StringType.PRINTABLESTRING.id;
+ } else {
+ tag = ASN1StringType.UTF8STRING.id;
+ }
+ this.tag = tag;
}
public AttributeValue(String hexString, byte[] encoded) {
@@ -117,11 +132,6 @@
}
public int getTag() {
- if (tag == -1) {
- tag = isPrintableString(rawString)
- ? ASN1StringType.PRINTABLESTRING.id
- : ASN1StringType.UTF8STRING.id;
- }
return tag;
}
@@ -129,9 +139,14 @@
if (hexString == null) {
if (!wasEncoded) {
//FIXME optimize me: what about reusable OutputStream???
- encoded = isPrintableString(rawString)
- ? ASN1StringType.PRINTABLESTRING.encode(rawString)
- : ASN1StringType.UTF8STRING.encode(rawString);
+ if (tag == ASN1StringType.IA5STRING.id) {
+ encoded = ASN1StringType.IA5STRING.encode(rawString);
+ } else if (tag == ASN1StringType.PRINTABLESTRING.id) {
+ encoded = ASN1StringType.PRINTABLESTRING.encode(rawString);
+ } else {
+ encoded = ASN1StringType.UTF8STRING.encode(rawString);
+ }
+ wasEncoded = true;
}
StringBuilder buf = new StringBuilder(encoded.length * 2 + 1);
@@ -157,6 +172,10 @@
return hexString;
}
+ public Collection<?> getValues(ASN1Type type) throws IOException {
+ return (Collection<?>) new ASN1SetOf(type).decode(encoded);
+ }
+
public void appendQEString(StringBuilder sb) {
sb.append('"');
if (hasQE) {
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
index 4946419..2f6fcb9 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/DNParser.java
@@ -25,10 +25,10 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.harmony.security.utils.ObjectIdentifier;
import org.apache.harmony.security.x501.AttributeTypeAndValue;
import org.apache.harmony.security.x501.AttributeValue;
-
/**
* Distinguished Name Parser.
*
@@ -390,32 +390,33 @@
if (attType == null) {
return list; //empty list of RDNs
}
+ ObjectIdentifier oid = AttributeTypeAndValue.getObjectIdentifier(attType);
List<AttributeTypeAndValue> atav = new ArrayList<AttributeTypeAndValue>();
while (true) {
if (pos == chars.length) {
//empty Attribute Value
- atav.add(new AttributeTypeAndValue(attType, new AttributeValue("", false)));
+ atav.add(new AttributeTypeAndValue(oid, new AttributeValue("", false, oid)));
list.add(0, atav);
return list;
}
switch (chars[pos]) {
case '"':
- atav.add(new AttributeTypeAndValue(attType, new AttributeValue(quotedAV(), hasQE)));
+ atav.add(new AttributeTypeAndValue(oid, new AttributeValue(quotedAV(), hasQE, oid)));
break;
case '#':
- atav.add(new AttributeTypeAndValue(attType, new AttributeValue(hexAV(), encoded)));
+ atav.add(new AttributeTypeAndValue(oid, new AttributeValue(hexAV(), encoded)));
break;
case '+':
case ',':
case ';': // compatibility with RFC 1779: semicolon can separate RDNs
//empty attribute value
- atav.add(new AttributeTypeAndValue(attType, new AttributeValue("", false)));
+ atav.add(new AttributeTypeAndValue(oid, new AttributeValue("", false, oid)));
break;
default:
- atav.add(new AttributeTypeAndValue(attType, new AttributeValue(
- escapedAV(), hasQE)));
+ atav.add(new AttributeTypeAndValue(oid,
+ new AttributeValue(escapedAV(), hasQE, oid)));
}
if (pos >= chars.length) {
@@ -435,6 +436,7 @@
if (attType == null) {
throw new IOException("Invalid distinguished name string");
}
+ oid = AttributeTypeAndValue.getObjectIdentifier(attType);
}
}
}
diff --git a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
index 9539054..92ff3a9 100644
--- a/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
+++ b/luni/src/main/java/org/apache/harmony/security/x509/Extensions.java
@@ -56,22 +56,31 @@
"2.5.29.30", "2.5.29.36", "2.5.29.37", "2.5.29.54");
// the values of extensions of the structure
- private List<Extension> extensions;
- private Set<String> critical;
- private Set<String> noncritical;
+ private final List<Extension> extensions;
+
+ // to speed up access, the following fields cache values computed
+ // from the extensions field, initialized using the "single-check
+ // idiom".
+
+ private volatile Set<String> critical;
+ private volatile Set<String> noncritical;
// the flag showing is there any unsupported critical extension
// in the list of extensions or not.
- private boolean hasUnsupported;
+ private volatile Boolean hasUnsupported;
+
// map containing the oid of extensions as a keys and
// Extension objects as values
- private HashMap<String, Extension> oidMap;
+ private volatile HashMap<String, Extension> oidMap;
+
// the ASN.1 encoded form of Extensions
private byte[] encoding;
/**
* Constructs an object representing the value of Extensions.
*/
- public Extensions() {}
+ public Extensions() {
+ this.extensions = null;
+ }
public Extensions(List<Extension> extensions) {
this.extensions = extensions;
@@ -85,27 +94,33 @@
* Returns the list of critical extensions.
*/
public Set<String> getCriticalExtensions() {
- if (critical == null) {
+ Set<String> resultCritical = critical;
+ if (resultCritical == null) {
makeOidsLists();
+ resultCritical = critical;
}
- return critical;
+ return resultCritical;
}
/**
* Returns the list of critical extensions.
*/
public Set<String> getNonCriticalExtensions() {
- if (noncritical == null) {
+ Set<String> resultNoncritical = noncritical;
+ if (resultNoncritical == null) {
makeOidsLists();
+ resultNoncritical = noncritical;
}
- return noncritical;
+ return resultNoncritical;
}
public boolean hasUnsupportedCritical() {
- if (critical == null) {
+ Boolean resultHasUnsupported = hasUnsupported;
+ if (resultHasUnsupported == null) {
makeOidsLists();
+ resultHasUnsupported = hasUnsupported;
}
- return hasUnsupported;
+ return resultHasUnsupported.booleanValue();
}
//
@@ -117,19 +132,23 @@
return;
}
int size = extensions.size();
- critical = new HashSet<String>(size);
- noncritical = new HashSet<String>(size);
+ Set<String> localCritical = new HashSet<String>(size);
+ Set<String> localNoncritical = new HashSet<String>(size);
+ Boolean localHasUnsupported = Boolean.FALSE;
for (Extension extension : extensions) {
String oid = extension.getExtnID();
if (extension.getCritical()) {
if (!SUPPORTED_CRITICAL.contains(oid)) {
- hasUnsupported = true;
+ localHasUnsupported = Boolean.TRUE;
}
- critical.add(oid);
+ localCritical.add(oid);
} else {
- noncritical.add(oid);
+ localNoncritical.add(oid);
}
}
+ this.critical = localCritical;
+ this.noncritical = localNoncritical;
+ this.hasUnsupported = localHasUnsupported;
}
/**
@@ -139,13 +158,15 @@
if (extensions == null) {
return null;
}
- if (oidMap == null) {
- oidMap = new HashMap<String, Extension>();
+ HashMap<String, Extension> localOidMap = oidMap;
+ if (localOidMap == null) {
+ localOidMap = new HashMap<String, Extension>();
for (Extension extension : extensions) {
- oidMap.put(extension.getExtnID(), extension);
+ localOidMap.put(extension.getExtnID(), extension);
}
+ this.oidMap = localOidMap;
}
- return oidMap.get(oid);
+ return localOidMap.get(oid);
}
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
deleted file mode 100644
index 59e20d6..0000000
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLProvider.java
+++ /dev/null
@@ -1,238 +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 org.apache.harmony.xnet.provider.jsse;
-
-import java.security.Provider;
-
-/**
- * Provider that goes through OpenSSL for operations.
- * <p>
- * Every algorithm should have its IANA assigned OID as an alias. See the following URLs for each type:
- * <ul>
- * <li><a href="http://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xml">Hash functions</a></li>
- * <li><a href="http://www.iana.org/assignments/dssc/dssc.xml">Signature algorithms</a></li>
- * <li><a href="http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html">NIST cryptographic algorithms</a></li>
- * </ul>
- */
-public final class OpenSSLProvider extends Provider {
- public static final String PROVIDER_NAME = "AndroidOpenSSL";
-
- public OpenSSLProvider() {
- super(PROVIDER_NAME, 1.0, "Android's OpenSSL-backed security provider");
-
- /* === SSL Contexts === */
- put("SSLContext.SSL", OpenSSLContextImpl.class.getName());
- put("SSLContext.SSLv3", OpenSSLContextImpl.class.getName());
- put("SSLContext.TLS", OpenSSLContextImpl.class.getName());
- put("SSLContext.TLSv1", OpenSSLContextImpl.class.getName());
- put("SSLContext.TLSv1.1", OpenSSLContextImpl.class.getName());
- put("SSLContext.TLSv1.2", OpenSSLContextImpl.class.getName());
- put("SSLContext.Default", DefaultSSLContextImpl.class.getName());
-
- /* === Message Digests === */
- put("MessageDigest.SHA-1",
- "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA1");
- put("Alg.Alias.MessageDigest.SHA1", "SHA-1");
- put("Alg.Alias.MessageDigest.SHA", "SHA-1");
- put("Alg.Alias.MessageDigest.1.3.14.3.2.26", "SHA-1");
-
- put("MessageDigest.SHA-256",
- "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA256");
- put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
- put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
-
- put("MessageDigest.SHA-384",
- "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA384");
- put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
- put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
-
- put("MessageDigest.SHA-512",
- "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$SHA512");
- put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
- put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
-
- // iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) md5(5)
- put("MessageDigest.MD5",
- "org.apache.harmony.xnet.provider.jsse.OpenSSLMessageDigestJDK$MD5");
- put("Alg.Alias.MessageDigest.1.2.840.113549.2.5", "MD5");
-
- /* == KeyPairGenerators == */
- put("KeyPairGenerator.RSA", OpenSSLRSAKeyPairGenerator.class.getName());
- put("Alg.Alias.KeyPairGenerator.1.2.840.113549.1.1.1", "RSA");
-
- put("KeyPairGenerator.DSA", OpenSSLDSAKeyPairGenerator.class.getName());
-
- put("KeyPairGenerator.EC", OpenSSLECKeyPairGenerator.class.getName());
-
- /* == KeyFactory == */
- put("KeyFactory.RSA", OpenSSLRSAKeyFactory.class.getName());
- put("Alg.Alias.KeyFactory.1.2.840.113549.1.1.1", "RSA");
-
- put("KeyFactory.DSA", OpenSSLDSAKeyFactory.class.getName());
-
- put("KeyFactory.EC", OpenSSLECKeyFactory.class.getName());
-
- /* == KeyAgreement == */
- put("KeyAgreement.ECDH", OpenSSLECDHKeyAgreement.class.getName());
-
- /* == Signatures == */
- put("Signature.MD5WithRSA", OpenSSLSignature.MD5RSA.class.getName());
- put("Alg.Alias.Signature.MD5WithRSAEncryption", "MD5WithRSA");
- put("Alg.Alias.Signature.MD5/RSA", "MD5WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.4", "MD5WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.2.5with1.2.840.113549.1.1.1", "MD5WithRSA");
-
- put("Signature.SHA1WithRSA", OpenSSLSignature.SHA1RSA.class.getName());
- put("Alg.Alias.Signature.SHA1WithRSAEncryption", "SHA1WithRSA");
- put("Alg.Alias.Signature.SHA1/RSA", "SHA1WithRSA");
- put("Alg.Alias.Signature.SHA-1/RSA", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.5", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.1", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.113549.1.1.5", "SHA1WithRSA");
- put("Alg.Alias.Signature.1.3.14.3.2.29", "SHA1WithRSA");
-
- put("Signature.SHA256WithRSA", OpenSSLSignature.SHA256RSA.class.getName());
- put("Alg.Alias.Signature.SHA256WithRSAEncryption", "SHA256WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.11", "SHA256WithRSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.1",
- "SHA256WithRSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.113549.1.1.11",
- "SHA256WithRSA");
-
- put("Signature.SHA384WithRSA", OpenSSLSignature.SHA384RSA.class.getName());
- put("Alg.Alias.Signature.SHA384WithRSAEncryption", "SHA384WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.12", "SHA384WithRSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.113549.1.1.1",
- "SHA384WithRSA");
-
- put("Signature.SHA512WithRSA", OpenSSLSignature.SHA512RSA.class.getName());
- put("Alg.Alias.Signature.SHA512WithRSAEncryption", "SHA512WithRSA");
- put("Alg.Alias.Signature.1.2.840.113549.1.1.13", "SHA512WithRSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.113549.1.1.1",
- "SHA512WithRSA");
-
- put("Signature.SHA1withDSA", OpenSSLSignature.SHA1DSA.class.getName());
- put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.DSA", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.1", "SHA1withDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10040.4.3", "SHA1withDSA");
- put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA");
- put("Alg.Alias.Signature.1.2.840.10040.4.3", "SHA1withDSA");
-
- put("Signature.NONEwithRSA", OpenSSLSignatureRawRSA.class.getName());
-
- put("Signature.ECDSA", OpenSSLSignature.SHA1ECDSA.class.getName());
- put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
- put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
- // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
- put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "ECDSA");
-
- // iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
- put("Signature.SHA256withECDSA", OpenSSLSignature.SHA256ECDSA.class.getName());
- // ecdsa-with-SHA256(2)
- put("Alg.Alias.Signature.1.2.840.10045.4.3.2", "SHA256withECDSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.1with1.2.840.10045.2.1", "SHA256withECDSA");
-
- put("Signature.SHA384withECDSA", OpenSSLSignature.SHA384ECDSA.class.getName());
- // ecdsa-with-SHA384(3)
- put("Alg.Alias.Signature.1.2.840.10045.4.3.3", "SHA384withECDSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.2with1.2.840.10045.2.1", "SHA384withECDSA");
-
- put("Signature.SHA512withECDSA", OpenSSLSignature.SHA512ECDSA.class.getName());
- // ecdsa-with-SHA512(4)
- put("Alg.Alias.Signature.1.2.840.10045.4.3.4", "SHA512withECDSA");
- put("Alg.Alias.Signature.2.16.840.1.101.3.4.2.3with1.2.840.10045.2.1", "SHA512withECDSA");
-
- /* === SecureRandom === */
- /*
- * We have to specify SHA1PRNG because various documentation mentions
- * that algorithm by name instead of just recommending calling
- * "new SecureRandom()"
- */
- put("SecureRandom.SHA1PRNG", OpenSSLRandom.class.getName());
- put("SecureRandom.SHA1PRNG ImplementedIn", "Software");
-
- /* === Cipher === */
- put("Cipher.RSA/ECB/NoPadding", OpenSSLCipherRSA.Raw.class.getName());
- put("Alg.Alias.Cipher.RSA/None/NoPadding", "RSA/ECB/NoPadding");
- put("Cipher.RSA/ECB/PKCS1Padding", OpenSSLCipherRSA.PKCS1.class.getName());
- put("Alg.Alias.Cipher.RSA/None/PKCS1Padding", "RSA/ECB/PKCS1Padding");
-
- /*
- * OpenSSL only supports a subset of modes, so we'll name them
- * explicitly here.
- */
- put("Cipher.AES/ECB/NoPadding", OpenSSLCipher.AES.ECB.NoPadding.class.getName());
- put("Cipher.AES/ECB/PKCS5Padding", OpenSSLCipher.AES.ECB.PKCS5Padding.class.getName());
- put("Cipher.AES/CBC/NoPadding", OpenSSLCipher.AES.CBC.NoPadding.class.getName());
- put("Cipher.AES/CBC/PKCS5Padding", OpenSSLCipher.AES.CBC.PKCS5Padding.class.getName());
- put("Cipher.AES/CFB/NoPadding", OpenSSLCipher.AES.CFB.NoPadding.class.getName());
- put("Cipher.AES/CFB/PKCS5Padding", OpenSSLCipher.AES.CFB.PKCS5Padding.class.getName());
- put("Cipher.AES/CTR/NoPadding", OpenSSLCipher.AES.CTR.NoPadding.class.getName());
- put("Cipher.AES/CTR/PKCS5Padding", OpenSSLCipher.AES.CTR.PKCS5Padding.class.getName());
- put("Cipher.AES/OFB/NoPadding", OpenSSLCipher.AES.OFB.NoPadding.class.getName());
- put("Cipher.AES/OFB/PKCS5Padding", OpenSSLCipher.AES.OFB.PKCS5Padding.class.getName());
-
- put("Cipher.DESEDE/CBC/NoPadding", OpenSSLCipher.DESEDE.CBC.NoPadding.class.getName());
- put("Cipher.DESEDE/CBC/PKCS5Padding", OpenSSLCipher.DESEDE.CBC.PKCS5Padding.class.getName());
- put("Cipher.DESEDE/CFB/NoPadding", OpenSSLCipher.DESEDE.CFB.NoPadding.class.getName());
- put("Cipher.DESEDE/CFB/PKCS5Padding", OpenSSLCipher.DESEDE.CFB.PKCS5Padding.class.getName());
- put("Cipher.DESEDE/ECB/NoPadding", OpenSSLCipher.DESEDE.ECB.NoPadding.class.getName());
- put("Cipher.DESEDE/ECB/PKCS5Padding", OpenSSLCipher.DESEDE.ECB.PKCS5Padding.class.getName());
- put("Cipher.DESEDE/OFB/NoPadding", OpenSSLCipher.DESEDE.OFB.NoPadding.class.getName());
- put("Cipher.DESEDE/OFB/PKCS5Padding", OpenSSLCipher.DESEDE.OFB.PKCS5Padding.class.getName());
-
- put("Cipher.ARC4", OpenSSLCipher.ARC4.class.getName());
-
- /* === Mac === */
-
- put("Mac.HmacMD5", OpenSSLMac.HmacMD5.class.getName());
-
- // PKCS#2 - iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2)
- // http://www.oid-info.com/get/1.2.840.113549.2
-
- // HMAC-SHA-1 PRF (7)
- put("Mac.HmacSHA1", OpenSSLMac.HmacSHA1.class.getName());
- put("Alg.Alias.Mac.1.2.840.113549.2.7", "HmacSHA1");
- put("Alg.Alias.Mac.HMAC-SHA1", "HmacSHA1");
- put("Alg.Alias.Mac.HMAC/SHA1", "HmacSHA1");
-
- // id-hmacWithSHA256 (9)
- put("Mac.HmacSHA256", OpenSSLMac.HmacSHA256.class.getName());
- put("Alg.Alias.Mac.1.2.840.113549.2.9", "HmacSHA256");
- put("Alg.Alias.Mac.HMAC-SHA256", "HmacSHA256");
- put("Alg.Alias.Mac.HMAC/SHA256", "HmacSHA256");
-
- // id-hmacWithSHA384 (10)
- put("Mac.HmacSHA384", OpenSSLMac.HmacSHA384.class.getName());
- put("Alg.Alias.Mac.1.2.840.113549.2.10", "HmacSHA384");
- put("Alg.Alias.Mac.HMAC-SHA384", "HmacSHA384");
- put("Alg.Alias.Mac.HMAC/SHA384", "HmacSHA384");
-
- // id-hmacWithSHA384 (11)
- put("Mac.HmacSHA512", OpenSSLMac.HmacSHA512.class.getName());
- put("Alg.Alias.Mac.1.2.840.113549.2.11", "HmacSHA512");
- put("Alg.Alias.Mac.HMAC-SHA512", "HmacSHA512");
- put("Alg.Alias.Mac.HMAC/SHA512", "HmacSHA512");
-
- /* === Certificate === */
-
- put("CertificateFactory.X509", OpenSSLX509CertificateFactory.class.getName());
- put("Alg.Alias.CertificateFactory.X.509", "X509");
- }
-}
diff --git a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
index 54117bb..c4ff069 100644
--- a/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
+++ b/luni/src/main/java/org/xml/sax/helpers/XMLReaderFactory.java
@@ -10,7 +10,7 @@
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@@ -126,7 +126,7 @@
in = loader.getResourceAsStream (service);
if (in != null) {
- reader = new BufferedReader (new InputStreamReader (in, Charsets.UTF_8));
+ reader = new BufferedReader (new InputStreamReader (in, StandardCharsets.UTF_8));
className = reader.readLine ();
in.close ();
}
diff --git a/luni/src/main/native/ExecStrings.cpp b/luni/src/main/native/ExecStrings.cpp
new file mode 100644
index 0000000..a6a62e2
--- /dev/null
+++ b/luni/src/main/native/ExecStrings.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ExecStrings"
+
+#include "ExecStrings.h"
+
+#include <stdlib.h>
+
+#include "cutils/log.h"
+#include "ScopedLocalRef.h"
+
+ExecStrings::ExecStrings(JNIEnv* env, jobjectArray java_string_array)
+ : env_(env), java_array_(java_string_array), array_(NULL) {
+ if (java_array_ == NULL) {
+ return;
+ }
+
+ jsize length = env_->GetArrayLength(java_array_);
+ array_ = new char*[length + 1];
+ array_[length] = NULL;
+ for (jsize i = 0; i < length; ++i) {
+ ScopedLocalRef<jstring> java_string(env_, reinterpret_cast<jstring>(env_->GetObjectArrayElement(java_array_, i)));
+ // We need to pass these strings to const-unfriendly code.
+ char* string = const_cast<char*>(env_->GetStringUTFChars(java_string.get(), NULL));
+ array_[i] = string;
+ }
+}
+
+ExecStrings::~ExecStrings() {
+ if (array_ == NULL) {
+ return;
+ }
+
+ // Temporarily clear any pending exception so we can clean up.
+ jthrowable pending_exception = env_->ExceptionOccurred();
+ if (pending_exception != NULL) {
+ env_->ExceptionClear();
+ }
+
+ jsize length = env_->GetArrayLength(java_array_);
+ for (jsize i = 0; i < length; ++i) {
+ ScopedLocalRef<jstring> java_string(env_, reinterpret_cast<jstring>(env_->GetObjectArrayElement(java_array_, i)));
+ env_->ReleaseStringUTFChars(java_string.get(), array_[i]);
+ }
+ delete[] array_;
+
+ // Re-throw any pending exception.
+ if (pending_exception != NULL) {
+ if (env_->Throw(pending_exception) < 0) {
+ ALOGE("Error rethrowing exception!");
+ }
+ }
+}
+
+char** ExecStrings::get() {
+ return array_;
+}
diff --git a/luni/src/main/native/ExecStrings.h b/luni/src/main/native/ExecStrings.h
new file mode 100644
index 0000000..f8a1b15
--- /dev/null
+++ b/luni/src/main/native/ExecStrings.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#include "jni.h"
+
+class ExecStrings {
+ public:
+ ExecStrings(JNIEnv* env, jobjectArray java_string_array);
+
+ ~ExecStrings();
+
+ char** get();
+
+ private:
+ JNIEnv* env_;
+ jobjectArray java_array_;
+ char** array_;
+
+ // Disallow copy and assignment.
+ ExecStrings(const ExecStrings&);
+ void operator=(const ExecStrings&);
+};
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index 219d663..d93282c 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -17,6 +17,8 @@
#ifndef ICU_UTILITIES_H_included
#define ICU_UTILITIES_H_included
+#define U_HAVE_STD_STRING 1 // For UnicodeString::toUTF8String(std::string&).
+
#include "jni.h"
#include "unicode/utypes.h" // For UErrorCode.
#include "unicode/locid.h" // For Locale.
diff --git a/luni/src/main/native/JniConstants.cpp b/luni/src/main/native/JniConstants.cpp
deleted file mode 100644
index 8693cf5..0000000
--- a/luni/src/main/native/JniConstants.cpp
+++ /dev/null
@@ -1,128 +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.
- */
-
-#include "JniConstants.h"
-#include "ScopedLocalRef.h"
-
-#include <stdlib.h>
-
-jclass JniConstants::bidiRunClass;
-jclass JniConstants::bigDecimalClass;
-jclass JniConstants::booleanClass;
-jclass JniConstants::byteArrayClass;
-jclass JniConstants::byteClass;
-jclass JniConstants::calendarClass;
-jclass JniConstants::charsetICUClass;
-jclass JniConstants::constructorClass;
-jclass JniConstants::deflaterClass;
-jclass JniConstants::doubleClass;
-jclass JniConstants::errnoExceptionClass;
-jclass JniConstants::fieldClass;
-jclass JniConstants::fieldPositionIteratorClass;
-jclass JniConstants::fileDescriptorClass;
-jclass JniConstants::gaiExceptionClass;
-jclass JniConstants::inet6AddressClass;
-jclass JniConstants::inetAddressClass;
-jclass JniConstants::inetSocketAddressClass;
-jclass JniConstants::inetUnixAddressClass;
-jclass JniConstants::inflaterClass;
-jclass JniConstants::inputStreamClass;
-jclass JniConstants::integerClass;
-jclass JniConstants::localeDataClass;
-jclass JniConstants::longClass;
-jclass JniConstants::methodClass;
-jclass JniConstants::mutableIntClass;
-jclass JniConstants::mutableLongClass;
-jclass JniConstants::objectClass;
-jclass JniConstants::objectArrayClass;
-jclass JniConstants::outputStreamClass;
-jclass JniConstants::parsePositionClass;
-jclass JniConstants::patternSyntaxExceptionClass;
-jclass JniConstants::realToStringClass;
-jclass JniConstants::socketClass;
-jclass JniConstants::socketImplClass;
-jclass JniConstants::stringClass;
-jclass JniConstants::structAddrinfoClass;
-jclass JniConstants::structFlockClass;
-jclass JniConstants::structGroupReqClass;
-jclass JniConstants::structLingerClass;
-jclass JniConstants::structPasswdClass;
-jclass JniConstants::structPollfdClass;
-jclass JniConstants::structStatClass;
-jclass JniConstants::structStatFsClass;
-jclass JniConstants::structTimevalClass;
-jclass JniConstants::structUcredClass;
-jclass JniConstants::structUtsnameClass;
-
-static jclass findClass(JNIEnv* env, const char* name) {
- ScopedLocalRef<jclass> localClass(env, env->FindClass(name));
- jclass result = reinterpret_cast<jclass>(env->NewGlobalRef(localClass.get()));
- if (result == NULL) {
- ALOGE("failed to find class '%s'", name);
- abort();
- }
- return result;
-}
-
-void JniConstants::init(JNIEnv* env) {
- bidiRunClass = findClass(env, "java/text/Bidi$Run");
- bigDecimalClass = findClass(env, "java/math/BigDecimal");
- booleanClass = findClass(env, "java/lang/Boolean");
- byteClass = findClass(env, "java/lang/Byte");
- byteArrayClass = findClass(env, "[B");
- calendarClass = findClass(env, "java/util/Calendar");
- charsetICUClass = findClass(env, "java/nio/charset/CharsetICU");
- constructorClass = findClass(env, "java/lang/reflect/Constructor");
- deflaterClass = findClass(env, "java/util/zip/Deflater");
- doubleClass = findClass(env, "java/lang/Double");
- errnoExceptionClass = findClass(env, "libcore/io/ErrnoException");
- fieldClass = findClass(env, "java/lang/reflect/Field");
- fieldPositionIteratorClass = findClass(env, "libcore/icu/NativeDecimalFormat$FieldPositionIterator");
- fileDescriptorClass = findClass(env, "java/io/FileDescriptor");
- gaiExceptionClass = findClass(env, "libcore/io/GaiException");
- inet6AddressClass = findClass(env, "java/net/Inet6Address");
- inetAddressClass = findClass(env, "java/net/InetAddress");
- inetSocketAddressClass = findClass(env, "java/net/InetSocketAddress");
- inetUnixAddressClass = findClass(env, "java/net/InetUnixAddress");
- inflaterClass = findClass(env, "java/util/zip/Inflater");
- inputStreamClass = findClass(env, "java/io/InputStream");
- integerClass = findClass(env, "java/lang/Integer");
- localeDataClass = findClass(env, "libcore/icu/LocaleData");
- longClass = findClass(env, "java/lang/Long");
- methodClass = findClass(env, "java/lang/reflect/Method");
- mutableIntClass = findClass(env, "libcore/util/MutableInt");
- mutableLongClass = findClass(env, "libcore/util/MutableLong");
- objectClass = findClass(env, "java/lang/Object");
- objectArrayClass = findClass(env, "[Ljava/lang/Object;");
- outputStreamClass = findClass(env, "java/io/OutputStream");
- parsePositionClass = findClass(env, "java/text/ParsePosition");
- patternSyntaxExceptionClass = findClass(env, "java/util/regex/PatternSyntaxException");
- realToStringClass = findClass(env, "java/lang/RealToString");
- socketClass = findClass(env, "java/net/Socket");
- socketImplClass = findClass(env, "java/net/SocketImpl");
- stringClass = findClass(env, "java/lang/String");
- structAddrinfoClass = findClass(env, "libcore/io/StructAddrinfo");
- structFlockClass = findClass(env, "libcore/io/StructFlock");
- structGroupReqClass = findClass(env, "libcore/io/StructGroupReq");
- structLingerClass = findClass(env, "libcore/io/StructLinger");
- structPasswdClass = findClass(env, "libcore/io/StructPasswd");
- structPollfdClass = findClass(env, "libcore/io/StructPollfd");
- structStatClass = findClass(env, "libcore/io/StructStat");
- structStatFsClass = findClass(env, "libcore/io/StructStatFs");
- structTimevalClass = findClass(env, "libcore/io/StructTimeval");
- structUcredClass = findClass(env, "libcore/io/StructUcred");
- structUtsnameClass = findClass(env, "libcore/io/StructUtsname");
-}
diff --git a/luni/src/main/native/JniConstants.h b/luni/src/main/native/JniConstants.h
deleted file mode 100644
index 8fd7bc8..0000000
--- a/luni/src/main/native/JniConstants.h
+++ /dev/null
@@ -1,95 +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.
- */
-
-#ifndef JNI_CONSTANTS_H_included
-#define JNI_CONSTANTS_H_included
-
-#include "JNIHelp.h"
-
-/**
- * A cache to avoid calling FindClass at runtime.
- *
- * Class lookup is relatively expensive (2.5us on passion-eng at the time of writing), so we do
- * all such lookups eagerly at VM startup. This means that code that never uses, say,
- * java.util.zip.Deflater still has to pay for the lookup, but it means that on a device the cost
- * is definitely paid during boot and amortized. A central cache also removes the temptation to
- * dynamically call FindClass rather than add a small cache to each file that needs one. Another
- * cost is that each class cached here requires a global reference, though in practice we save
- * enough by not having a global reference for each file that uses a class such as java.lang.String
- * which is used in several files.
- *
- * FindClass is still called in a couple of situations: when throwing exceptions, and in some of
- * the serialization code. The former is clearly not a performance case, and we're currently
- * assuming that neither is the latter.
- *
- * TODO: similar arguments hold for field and method IDs; we should cache them centrally too.
- */
-struct JniConstants {
- static void init(JNIEnv* env);
-
- static jclass bidiRunClass;
- static jclass bigDecimalClass;
- static jclass booleanClass;
- static jclass byteArrayClass;
- static jclass byteClass;
- static jclass calendarClass;
- static jclass charsetICUClass;
- static jclass constructorClass;
- static jclass deflaterClass;
- static jclass doubleClass;
- static jclass errnoExceptionClass;
- static jclass fieldClass;
- static jclass fieldPositionIteratorClass;
- static jclass fileDescriptorClass;
- static jclass gaiExceptionClass;
- static jclass inet6AddressClass;
- static jclass inetAddressClass;
- static jclass inetSocketAddressClass;
- static jclass inetUnixAddressClass;
- static jclass inflaterClass;
- static jclass inputStreamClass;
- static jclass integerClass;
- static jclass localeDataClass;
- static jclass longClass;
- static jclass methodClass;
- static jclass mutableIntClass;
- static jclass mutableLongClass;
- static jclass objectClass;
- static jclass objectArrayClass;
- static jclass outputStreamClass;
- static jclass parsePositionClass;
- static jclass patternSyntaxExceptionClass;
- static jclass realToStringClass;
- static jclass socketClass;
- static jclass socketImplClass;
- static jclass stringClass;
- static jclass structAddrinfoClass;
- static jclass structFlockClass;
- static jclass structGroupReqClass;
- static jclass structLingerClass;
- static jclass structPasswdClass;
- static jclass structPollfdClass;
- static jclass structStatClass;
- static jclass structStatFsClass;
- static jclass structTimevalClass;
- static jclass structUcredClass;
- static jclass structUtsnameClass;
-};
-
-#define NATIVE_METHOD(className, functionName, signature) \
- { #functionName, signature, reinterpret_cast<void*>(className ## _ ## functionName) }
-
-#endif // JNI_CONSTANTS_H_included
diff --git a/luni/src/main/native/Portability.h b/luni/src/main/native/Portability.h
index 833d5bb..60b7062 100644
--- a/luni/src/main/native/Portability.h
+++ b/luni/src/main/native/Portability.h
@@ -72,9 +72,7 @@
#include <byteswap.h>
#include <sys/sendfile.h>
-
-// For statfs(3).
-#include <sys/vfs.h> // Bionic doesn't have <sys/statvfs.h>
+#include <sys/statvfs.h>
#endif
diff --git a/luni/src/main/native/Register.cpp b/luni/src/main/native/Register.cpp
index c94cd5d..54aecef 100644
--- a/luni/src/main/native/Register.cpp
+++ b/luni/src/main/native/Register.cpp
@@ -31,13 +31,13 @@
ScopedLocalFrame localFrame(env);
- JniConstants::init(env);
-
#define REGISTER(FN) extern void FN(JNIEnv*); FN(env)
REGISTER(register_java_io_Console);
REGISTER(register_java_io_File);
REGISTER(register_java_io_ObjectStreamClass);
REGISTER(register_java_lang_Character);
+ REGISTER(register_java_lang_Double);
+ REGISTER(register_java_lang_Float);
REGISTER(register_java_lang_Math);
REGISTER(register_java_lang_ProcessManager);
REGISTER(register_java_lang_RealToString);
@@ -55,6 +55,7 @@
REGISTER(register_java_util_zip_Deflater);
REGISTER(register_java_util_zip_Inflater);
REGISTER(register_libcore_icu_AlphabeticIndex);
+ REGISTER(register_libcore_icu_DateIntervalFormat);
REGISTER(register_libcore_icu_ICU);
REGISTER(register_libcore_icu_NativeBreakIterator);
REGISTER(register_libcore_icu_NativeCollation);
@@ -72,7 +73,7 @@
REGISTER(register_libcore_net_RawSocket);
REGISTER(register_org_apache_harmony_dalvik_NativeTestTarget);
REGISTER(register_org_apache_harmony_xml_ExpatParser);
- REGISTER(register_org_apache_harmony_xnet_provider_jsse_NativeCrypto);
+ REGISTER(register_org_conscrypt_NativeCrypto);
REGISTER(register_sun_misc_Unsafe);
#undef REGISTER
return JNI_VERSION_1_6;
diff --git a/luni/src/main/native/java_lang_Character.cpp b/luni/src/main/native/java_lang_Character.cpp
index 7dbef90..de1800e 100644
--- a/luni/src/main/native/java_lang_Character.cpp
+++ b/luni/src/main/native/java_lang_Character.cpp
@@ -135,6 +135,14 @@
return ublock_getCode(codePoint);
}
+static jboolean Character_isAlphabetic(JNIEnv*, jclass, jint codePoint) {
+ return u_hasBinaryProperty(codePoint, UCHAR_ALPHABETIC);
+}
+
+static jboolean Character_isIdeographic(JNIEnv*, jclass, jint codePoint) {
+ return u_hasBinaryProperty(codePoint, UCHAR_IDEOGRAPHIC);
+}
+
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(Character, digitImpl, "!(II)I"),
NATIVE_METHOD(Character, forNameImpl, "(Ljava/lang/String;)I"),
@@ -142,9 +150,11 @@
NATIVE_METHOD(Character, getNameImpl, "(I)Ljava/lang/String;"),
NATIVE_METHOD(Character, getNumericValueImpl, "!(I)I"),
NATIVE_METHOD(Character, getTypeImpl, "!(I)I"),
+ NATIVE_METHOD(Character, isAlphabetic, "!(I)Z"),
NATIVE_METHOD(Character, isDefinedImpl, "!(I)Z"),
NATIVE_METHOD(Character, isDigitImpl, "!(I)Z"),
NATIVE_METHOD(Character, isIdentifierIgnorableImpl, "!(I)Z"),
+ NATIVE_METHOD(Character, isIdeographic, "!(I)Z"),
NATIVE_METHOD(Character, isLetterImpl, "!(I)Z"),
NATIVE_METHOD(Character, isLetterOrDigitImpl, "!(I)Z"),
NATIVE_METHOD(Character, isLowerCaseImpl, "!(I)Z"),
diff --git a/luni/src/main/native/java_lang_Double.cpp b/luni/src/main/native/java_lang_Double.cpp
new file mode 100644
index 0000000..259be30
--- /dev/null
+++ b/luni/src/main/native/java_lang_Double.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Double"
+
+#include "JNIHelp.h"
+#include "JniConstants.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+union Double {
+ uint64_t bits;
+ double d;
+};
+
+static const jlong NaN = 0x7ff8000000000000ULL;
+
+static jlong Double_doubleToLongBits(JNIEnv*, jclass, jdouble val) {
+ Double d;
+ d.d = val;
+ // For this method all values in the NaN range are normalized to the canonical NaN value.
+ return isnan(d.d) ? NaN : d.bits;
+}
+
+static jlong Double_doubleToRawLongBits(JNIEnv*, jclass, jdouble val) {
+ Double d;
+ d.d = val;
+ return d.bits;
+}
+
+static jdouble Double_longBitsToDouble(JNIEnv*, jclass, jlong val) {
+ Double d;
+ d.bits = val;
+ return d.d;
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Double, doubleToLongBits, "(D)J"),
+ NATIVE_METHOD(Double, doubleToRawLongBits, "(D)J"),
+ NATIVE_METHOD(Double, longBitsToDouble, "(J)D"),
+};
+int register_java_lang_Double(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "java/lang/Double", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/java_lang_Float.cpp b/luni/src/main/native/java_lang_Float.cpp
new file mode 100644
index 0000000..59544db
--- /dev/null
+++ b/luni/src/main/native/java_lang_Float.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2005 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.
+ */
+
+#define LOG_TAG "Float"
+
+#include "JNIHelp.h"
+#include "JniConstants.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+union Float {
+ unsigned int bits;
+ float f;
+};
+
+static const jint NaN = 0x7fc00000;
+
+static jint Float_floatToIntBits(JNIEnv*, jclass, jfloat val) {
+ Float f;
+ f.f = val;
+ // For this method all values in the NaN range are normalized to the canonical NaN value.
+ return isnanf(f.f) ? NaN : f.bits;
+}
+
+jint Float_floatToRawIntBits(JNIEnv*, jclass, jfloat val) {
+ Float f;
+ f.f = val;
+ return f.bits;
+}
+
+jfloat Float_intBitsToFloat(JNIEnv*, jclass, jint val) {
+ Float f;
+ f.bits = val;
+ return f.f;
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(Float, floatToIntBits, "(F)I"),
+ NATIVE_METHOD(Float, floatToRawIntBits, "(F)I"),
+ NATIVE_METHOD(Float, intBitsToFloat, "(I)F"),
+};
+int register_java_lang_Float(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "java/lang/Float", gMethods, NELEM(gMethods));
+}
diff --git a/luni/src/main/native/java_lang_Math.cpp b/luni/src/main/native/java_lang_Math.cpp
index 273820e..784b84d 100644
--- a/luni/src/main/native/java_lang_Math.cpp
+++ b/luni/src/main/native/java_lang_Math.cpp
@@ -23,6 +23,14 @@
#include <stdlib.h>
#include <math.h>
+static jdouble Math_sin(JNIEnv*, jclass, jdouble a) {
+ return sin(a);
+}
+
+static jdouble Math_cos(JNIEnv*, jclass, jdouble a) {
+ return cos(a);
+}
+
static jdouble Math_tan(JNIEnv*, jclass, jdouble a) {
return tan(a);
}
@@ -91,6 +99,10 @@
return cbrt(a);
}
+static jdouble Math_sqrt(JNIEnv*, jclass, jdouble a) {
+ return sqrt(a);
+}
+
static jdouble Math_expm1(JNIEnv*, jclass, jdouble a) {
return expm1(a);
}
@@ -115,6 +127,7 @@
NATIVE_METHOD(Math, atan2, "!(DD)D"),
NATIVE_METHOD(Math, cbrt, "!(D)D"),
NATIVE_METHOD(Math, ceil, "!(D)D"),
+ NATIVE_METHOD(Math, cos, "!(D)D"),
NATIVE_METHOD(Math, cosh, "!(D)D"),
NATIVE_METHOD(Math, exp, "!(D)D"),
NATIVE_METHOD(Math, expm1, "!(D)D"),
@@ -126,7 +139,9 @@
NATIVE_METHOD(Math, nextafter, "!(DD)D"),
NATIVE_METHOD(Math, pow, "!(DD)D"),
NATIVE_METHOD(Math, rint, "!(D)D"),
+ NATIVE_METHOD(Math, sin, "!(D)D"),
NATIVE_METHOD(Math, sinh, "!(D)D"),
+ NATIVE_METHOD(Math, sqrt, "!(D)D"),
NATIVE_METHOD(Math, tan, "!(D)D"),
NATIVE_METHOD(Math, tanh, "!(D)D"),
};
diff --git a/luni/src/main/native/java_lang_ProcessManager.cpp b/luni/src/main/native/java_lang_ProcessManager.cpp
index e3f0f45..a74ba8b 100644
--- a/luni/src/main/native/java_lang_ProcessManager.cpp
+++ b/luni/src/main/native/java_lang_ProcessManager.cpp
@@ -16,223 +16,222 @@
#define LOG_TAG "ProcessManager"
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
+#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include "cutils/log.h"
#include "jni.h"
+#include "ExecStrings.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "Portability.h"
#include "ScopedLocalRef.h"
-#include "cutils/log.h"
#include "toStringArray.h"
-/** Close all open fds > 2 (i.e. everything but stdin/out/err), != skipFd. */
-static void closeNonStandardFds(int skipFd1, int skipFd2) {
- // TODO: rather than close all these non-open files, we could look in /proc/self/fd.
- rlimit rlimit;
- getrlimit(RLIMIT_NOFILE, &rlimit);
- const int max_fd = rlimit.rlim_max;
- for (int fd = 3; fd < max_fd; ++fd) {
- if (fd != skipFd1 && fd != skipFd2) {
- close(fd);
- }
+static void CloseNonStandardFds(int status_pipe_fd) {
+ // On Cygwin, Linux, and Solaris, the best way to close iterates over "/proc/self/fd/".
+ const char* fd_path = "/proc/self/fd";
+#ifdef __APPLE__
+ // On Mac OS, there's "/dev/fd/" which Linux seems to link to "/proc/self/fd/",
+ // but which on Solaris appears to be something quite different.
+ fd_path = "/dev/fd";
+#endif
+
+ // Keep track of the system properties fd so we don't close it.
+ int properties_fd = -1;
+ char* properties_fd_string = getenv("ANDROID_PROPERTY_WORKSPACE");
+ if (properties_fd_string != NULL) {
+ properties_fd = atoi(properties_fd_string);
+ }
+
+ DIR* d = opendir(fd_path);
+ int dir_fd = dirfd(d);
+ dirent* e;
+ while ((e = readdir(d)) != NULL) {
+ char* end;
+ int fd = strtol(e->d_name, &end, 10);
+ if (!*end) {
+ if (fd > STDERR_FILENO && fd != dir_fd && fd != status_pipe_fd && fd != properties_fd) {
+ close(fd);
+ }
}
+ }
+ closedir(d);
}
-#define PIPE_COUNT (4) // number of pipes used to communicate with child proc
+#define PIPE_COUNT 4 // Number of pipes used to communicate with child.
-/** Closes all pipes in the given array. */
-static void closePipes(int pipes[], int skipFd) {
- for (int i = 0; i < PIPE_COUNT * 2; i++) {
- int fd = pipes[i];
- if (fd == -1) {
- return;
- }
- if (fd != skipFd) {
- close(pipes[i]);
- }
+static void ClosePipes(int pipes[], int skip_fd) {
+ for (int i = 0; i < PIPE_COUNT * 2; i++) {
+ int fd = pipes[i];
+ if (fd != -1 && fd != skip_fd) {
+ close(pipes[i]);
}
+ }
+}
+
+static void AbortChild(int status_pipe_fd) {
+ int error = errno;
+ TEMP_FAILURE_RETRY(write(status_pipe_fd, &error, sizeof(int)));
+ close(status_pipe_fd);
+ _exit(127);
}
/** Executes a command in a child process. */
-static pid_t executeProcess(JNIEnv* env, char** commands, char** environment,
- const char* workingDirectory, jobject inDescriptor,
- jobject outDescriptor, jobject errDescriptor,
- jboolean redirectErrorStream) {
+static pid_t ExecuteProcess(JNIEnv* env, char** commands, char** environment,
+ const char* workingDirectory, jobject inDescriptor,
+ jobject outDescriptor, jobject errDescriptor,
+ jboolean redirectErrorStream) {
- // Keep track of the system properties fd so we don't close it.
- int androidSystemPropertiesFd = -1;
- char* fdString = getenv("ANDROID_PROPERTY_WORKSPACE");
- if (fdString) {
- androidSystemPropertiesFd = atoi(fdString);
+ // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
+ int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+ for (int i = 0; i < PIPE_COUNT; i++) {
+ if (pipe(pipes + i * 2) == -1) {
+ jniThrowIOException(env, errno);
+ ClosePipes(pipes, -1);
+ return -1;
+ }
+ }
+ int stdinIn = pipes[0];
+ int stdinOut = pipes[1];
+ int stdoutIn = pipes[2];
+ int stdoutOut = pipes[3];
+ int stderrIn = pipes[4];
+ int stderrOut = pipes[5];
+ int statusIn = pipes[6];
+ int statusOut = pipes[7];
+
+ pid_t childPid = fork();
+
+ // If fork() failed...
+ if (childPid == -1) {
+ jniThrowIOException(env, errno);
+ ClosePipes(pipes, -1);
+ return -1;
+ }
+
+ // If this is the child process...
+ if (childPid == 0) {
+ // Note: We cannot malloc(3) or free(3) after this point!
+ // A thread in the parent that no longer exists in the child may have held the heap lock
+ // when we forked, so an attempt to malloc(3) or free(3) would result in deadlock.
+
+ // Replace stdin, out, and err with pipes.
+ dup2(stdinIn, 0);
+ dup2(stdoutOut, 1);
+ if (redirectErrorStream) {
+ dup2(stdoutOut, 2);
+ } else {
+ dup2(stderrOut, 2);
}
- // Create 4 pipes: stdin, stdout, stderr, and an exec() status pipe.
- int pipes[PIPE_COUNT * 2] = { -1, -1, -1, -1, -1, -1, -1, -1 };
- for (int i = 0; i < PIPE_COUNT; i++) {
- if (pipe(pipes + i * 2) == -1) {
- jniThrowIOException(env, errno);
- closePipes(pipes, -1);
- return -1;
- }
- }
- int stdinIn = pipes[0];
- int stdinOut = pipes[1];
- int stdoutIn = pipes[2];
- int stdoutOut = pipes[3];
- int stderrIn = pipes[4];
- int stderrOut = pipes[5];
- int statusIn = pipes[6];
- int statusOut = pipes[7];
+ // Close all but statusOut. This saves some work in the next step.
+ ClosePipes(pipes, statusOut);
- pid_t childPid = fork();
+ // Make statusOut automatically close if execvp() succeeds.
+ fcntl(statusOut, F_SETFD, FD_CLOEXEC);
- // If fork() failed...
- if (childPid == -1) {
- jniThrowIOException(env, errno);
- closePipes(pipes, -1);
- return -1;
+ // Close remaining unwanted open fds.
+ CloseNonStandardFds(statusOut);
+
+ // Switch to working directory.
+ if (workingDirectory != NULL) {
+ if (chdir(workingDirectory) == -1) {
+ AbortChild(statusOut);
+ }
}
- // If this is the child process...
- if (childPid == 0) {
- /*
- * Note: We cannot malloc(3) or free(3) after this point!
- * A thread in the parent that no longer exists in the child may have held the heap lock
- * when we forked, so an attempt to malloc(3) or free(3) would result in deadlock.
- */
-
- // Replace stdin, out, and err with pipes.
- dup2(stdinIn, 0);
- dup2(stdoutOut, 1);
- if (redirectErrorStream) {
- dup2(stdoutOut, 2);
- } else {
- dup2(stderrOut, 2);
- }
-
- // Close all but statusOut. This saves some work in the next step.
- closePipes(pipes, statusOut);
-
- // Make statusOut automatically close if execvp() succeeds.
- fcntl(statusOut, F_SETFD, FD_CLOEXEC);
-
- // Close remaining unwanted open fds.
- closeNonStandardFds(statusOut, androidSystemPropertiesFd);
-
- // Switch to working directory.
- if (workingDirectory != NULL) {
- if (chdir(workingDirectory) == -1) {
- goto execFailed;
- }
- }
-
- // Set up environment.
- if (environment != NULL) {
- extern char** environ; // Standard, but not in any header file.
- environ = environment;
- }
-
- // Execute process. By convention, the first argument in the arg array
- // should be the command itself. In fact, I get segfaults when this
- // isn't the case.
- execvp(commands[0], commands);
-
- // If we got here, execvp() failed or the working dir was invalid.
-execFailed:
- int error = errno;
- write(statusOut, &error, sizeof(int));
- close(statusOut);
- exit(error);
+ // Set up environment.
+ if (environment != NULL) {
+ extern char** environ; // Standard, but not in any header file.
+ environ = environment;
}
- // This is the parent process.
+ // Execute process. By convention, the first argument in the arg array
+ // should be the command itself.
+ execvp(commands[0], commands);
+ AbortChild(statusOut);
+ }
- // Close child's pipe ends.
- close(stdinIn);
- close(stdoutOut);
- close(stderrOut);
- close(statusOut);
+ // This is the parent process.
- // Check status pipe for an error code. If execvp() succeeds, the other
- // end of the pipe should automatically close, in which case, we'll read
- // nothing.
- int result;
- int count = read(statusIn, &result, sizeof(int));
- close(statusIn);
- if (count > 0) {
- jniThrowIOException(env, result);
+ // Close child's pipe ends.
+ close(stdinIn);
+ close(stdoutOut);
+ close(stderrOut);
+ close(statusOut);
- close(stdoutIn);
- close(stdinOut);
- close(stderrIn);
+ // Check status pipe for an error code. If execvp(2) succeeds, the other
+ // end of the pipe should automatically close, in which case, we'll read
+ // nothing.
+ int child_errno;
+ ssize_t count = TEMP_FAILURE_RETRY(read(statusIn, &child_errno, sizeof(int)));
+ close(statusIn);
+ if (count > 0) {
+ // chdir(2) or execvp(2) in the child failed.
+ // TODO: track which so we can be more specific in the detail message.
+ jniThrowIOException(env, child_errno);
- return -1;
+ close(stdoutIn);
+ close(stdinOut);
+ close(stderrIn);
+
+ // Reap our zombie child right away.
+ int status;
+ int rc = TEMP_FAILURE_RETRY(waitpid(childPid, &status, 0));
+ if (rc == -1) {
+ ALOGW("waitpid on failed exec failed: %s", strerror(errno));
}
- // Fill in file descriptor wrappers.
- jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
- jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
- jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
+ return -1;
+ }
- return childPid;
+ // Fill in file descriptor wrappers.
+ jniSetFileDescriptorOfFD(env, inDescriptor, stdoutIn);
+ jniSetFileDescriptorOfFD(env, outDescriptor, stdinOut);
+ jniSetFileDescriptorOfFD(env, errDescriptor, stderrIn);
+
+ return childPid;
}
/**
- * Converts Java String[] to char** and delegates to executeProcess().
+ * Converts Java String[] to char** and delegates to ExecuteProcess().
*/
static pid_t ProcessManager_exec(JNIEnv* env, jclass, jobjectArray javaCommands,
- jobjectArray javaEnvironment, jstring javaWorkingDirectory,
- jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
- jboolean redirectErrorStream) {
+ jobjectArray javaEnvironment, jstring javaWorkingDirectory,
+ jobject inDescriptor, jobject outDescriptor, jobject errDescriptor,
+ jboolean redirectErrorStream) {
- // Copy commands into char*[].
- char** commands = convertStrings(env, javaCommands);
+ ExecStrings commands(env, javaCommands);
+ ExecStrings environment(env, javaEnvironment);
- // Extract working directory string.
- const char* workingDirectory = NULL;
- if (javaWorkingDirectory != NULL) {
- workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
- }
+ // Extract working directory string.
+ const char* workingDirectory = NULL;
+ if (javaWorkingDirectory != NULL) {
+ workingDirectory = env->GetStringUTFChars(javaWorkingDirectory, NULL);
+ }
- // Convert environment array.
- char** environment = convertStrings(env, javaEnvironment);
+ pid_t result = ExecuteProcess(env, commands.get(), environment.get(), workingDirectory,
+ inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
- pid_t result = executeProcess(env, commands, environment, workingDirectory,
- inDescriptor, outDescriptor, errDescriptor, redirectErrorStream);
+ // Clean up working directory string.
+ if (javaWorkingDirectory != NULL) {
+ env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
+ }
- // Temporarily clear exception so we can clean up.
- jthrowable exception = env->ExceptionOccurred();
- env->ExceptionClear();
-
- freeStrings(env, javaEnvironment, environment);
-
- // Clean up working directory string.
- if (javaWorkingDirectory != NULL) {
- env->ReleaseStringUTFChars(javaWorkingDirectory, workingDirectory);
- }
-
- freeStrings(env, javaCommands, commands);
-
- // Re-throw exception if present.
- if (exception != NULL) {
- if (env->Throw(exception) < 0) {
- ALOGE("Error rethrowing exception!");
- }
- }
-
- return result;
+ return result;
}
-static JNINativeMethod methods[] = {
- NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"),
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(ProcessManager, exec, "([Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;Z)I"),
};
void register_java_lang_ProcessManager(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/lang/ProcessManager", methods, NELEM(methods));
+ jniRegisterNativeMethods(env, "java/lang/ProcessManager", gMethods, NELEM(gMethods));
}
diff --git a/luni/src/main/native/java_lang_System.cpp b/luni/src/main/native/java_lang_System.cpp
index 8cfd070..0686310 100644
--- a/luni/src/main/native/java_lang_System.cpp
+++ b/luni/src/main/native/java_lang_System.cpp
@@ -30,6 +30,8 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/time.h>
+#include <time.h>
#include <unistd.h>
static void System_log(JNIEnv* env, jclass, jchar type, jstring javaMessage, jthrowable exception) {
@@ -83,8 +85,36 @@
return toStringArray(env, properties);
}
+static jlong System_currentTimeMillis(JNIEnv*, jclass) {
+ timeval now;
+ gettimeofday(&now, NULL);
+ jlong when = now.tv_sec * 1000LL + now.tv_usec / 1000;
+ return when;
+}
+
+static jlong System_nanoTime(JNIEnv*, jclass) {
+ timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return now.tv_sec * 1000000000LL + now.tv_nsec;
+}
+
+static jstring System_mapLibraryName(JNIEnv* env, jclass, jstring javaName) {
+ ScopedUtfChars name(env, javaName);
+ if (name.c_str() == NULL) {
+ return NULL;
+ }
+ char* mappedName = NULL;
+ asprintf(&mappedName, OS_SHARED_LIB_FORMAT_STR, name.c_str());
+ jstring result = env->NewStringUTF(mappedName);
+ free(mappedName);
+ return result;
+}
+
static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(System, currentTimeMillis, "()J"),
NATIVE_METHOD(System, log, "(CLjava/lang/String;Ljava/lang/Throwable;)V"),
+ NATIVE_METHOD(System, mapLibraryName, "(Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(System, nanoTime, "()J"),
NATIVE_METHOD(System, setFieldImpl, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V"),
NATIVE_METHOD(System, specialProperties, "()[Ljava/lang/String;"),
};
diff --git a/luni/src/main/native/java_math_NativeBN.cpp b/luni/src/main/native/java_math_NativeBN.cpp
index 5e111d7..158dfac 100644
--- a/luni/src/main/native/java_math_NativeBN.cpp
+++ b/luni/src/main/native/java_math_NativeBN.cpp
@@ -14,14 +14,11 @@
* limitations under the License.
*/
-/*
- * Native glue for Java class org.openssl.NativeBN
- */
-
#define LOG_TAG "NativeBN"
#include "JNIHelp.h"
#include "JniConstants.h"
+#include "JniException.h"
#include "ScopedPrimitiveArray.h"
#include "ScopedUtfChars.h"
#include "StaticAssert.h"
@@ -33,260 +30,286 @@
#include <stdio.h>
struct BN_CTX_Deleter {
- void operator()(BN_CTX* p) const {
- BN_CTX_free(p);
- }
+ void operator()(BN_CTX* p) const {
+ BN_CTX_free(p);
+ }
};
typedef UniquePtr<BN_CTX, BN_CTX_Deleter> Unique_BN_CTX;
-static int isValidHandle (JNIEnv* env, void* handle, const char* message) {
- if (handle == NULL) {
- jniThrowNullPointerException(env, message);
- return JNI_FALSE;
- }
- return JNI_TRUE;
+static BIGNUM* toBigNum(jlong address) {
+ return reinterpret_cast<BIGNUM*>(static_cast<uintptr_t>(address));
}
-static int oneValidHandle (JNIEnv* env, void* a)
-{
- return isValidHandle(env, a, "Mandatory handle (first) passed as null");
+static bool throwExceptionIfNecessary(JNIEnv* env) {
+ long error = ERR_get_error();
+ if (error == 0) {
+ return false;
+ }
+ char message[256];
+ ERR_error_string_n(error, message, sizeof(message));
+ int reason = ERR_GET_REASON(error);
+ if (reason == BN_R_DIV_BY_ZERO) {
+ jniThrowException(env, "java/lang/ArithmeticException", "BigInteger division by zero");
+ } else if (reason == BN_R_NO_INVERSE) {
+ jniThrowException(env, "java/lang/ArithmeticException", "BigInteger not invertible");
+ } else if (reason == ERR_R_MALLOC_FAILURE) {
+ jniThrowOutOfMemoryError(env, message);
+ } else {
+ jniThrowException(env, "java/lang/ArithmeticException", message);
+ }
+ return true;
}
-static int twoValidHandles (JNIEnv* env, void* a, void* b)
-{
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return isValidHandle(env, b, "Mandatory handle (second) passed as null");
+static int isValidHandle(JNIEnv* env, jlong handle, const char* message) {
+ if (handle == 0) {
+ jniThrowNullPointerException(env, message);
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
}
-static int threeValidHandles (JNIEnv* env, void* a, void* b, void* c)
-{
- if (!twoValidHandles(env, a, b)) return JNI_FALSE;
- return isValidHandle(env, c, "Mandatory handle (third) passed as null");
+static int oneValidHandle(JNIEnv* env, jlong a) {
+ return isValidHandle(env, a, "Mandatory handle (first) passed as null");
}
-static int fourValidHandles (JNIEnv* env, void* a, void* b, void* c, void* d)
-{
- if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
- return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
+static int twoValidHandles(JNIEnv* env, jlong a, jlong b) {
+ if (!oneValidHandle(env, a)) return JNI_FALSE;
+ return isValidHandle(env, b, "Mandatory handle (second) passed as null");
}
-static unsigned long NativeBN_ERR_get_error(JNIEnv*, jclass) {
- return ERR_get_error();
+static int threeValidHandles(JNIEnv* env, jlong a, jlong b, jlong c) {
+ if (!twoValidHandles(env, a, b)) return JNI_FALSE;
+ return isValidHandle(env, c, "Mandatory handle (third) passed as null");
}
-static jstring NativeBN_ERR_error_string(JNIEnv* env, jclass, unsigned long e) {
- char* errStr = ERR_error_string(e, NULL);
- return env->NewStringUTF(errStr);
+static int fourValidHandles(JNIEnv* env, jlong a, jlong b, jlong c, jlong d) {
+ if (!threeValidHandles(env, a, b, c)) return JNI_FALSE;
+ return isValidHandle(env, d, "Mandatory handle (fourth) passed as null");
}
-static BIGNUM* NativeBN_BN_new(JNIEnv*, jclass) {
- return BN_new();
+static jlong NativeBN_BN_new(JNIEnv* env, jclass) {
+ jlong result = static_cast<jlong>(reinterpret_cast<uintptr_t>(BN_new()));
+ throwExceptionIfNecessary(env);
+ return result;
}
-static void NativeBN_BN_free(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return;
- BN_free(a);
+static void NativeBN_BN_free(JNIEnv* env, jclass, jlong a) {
+ if (!oneValidHandle(env, a)) return;
+ BN_free(toBigNum(a));
}
-static int NativeBN_BN_cmp(JNIEnv* env, jclass, BIGNUM* a, BIGNUM* b) {
- if (!twoValidHandles(env, a, b)) return 1;
- return BN_cmp(a, b);
+static int NativeBN_BN_cmp(JNIEnv* env, jclass, jlong a, jlong b) {
+ if (!twoValidHandles(env, a, b)) return 1;
+ return BN_cmp(toBigNum(a), toBigNum(b));
}
-static jboolean NativeBN_BN_copy(JNIEnv* env, jclass, BIGNUM* to, BIGNUM* from) {
- if (!twoValidHandles(env, to, from)) return JNI_FALSE;
- return (BN_copy(to, from) != NULL);
+static void NativeBN_BN_copy(JNIEnv* env, jclass, jlong to, jlong from) {
+ if (!twoValidHandles(env, to, from)) return;
+ BN_copy(toBigNum(to), toBigNum(from));
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_putULongInt(JNIEnv* env, jclass, BIGNUM* a, unsigned long long dw, jboolean neg) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
+static void NativeBN_putULongInt(JNIEnv* env, jclass, jlong a0, unsigned long long dw, jboolean neg) {
+ if (!oneValidHandle(env, a0)) return;
unsigned int hi = dw >> 32; // This shifts without sign extension.
- int lo = (int)dw; // This truncates implicitely.
+ int lo = (int)dw; // This truncates implicitly.
// cf. litEndInts2bn:
+ BIGNUM* a = toBigNum(a0);
bn_check_top(a);
- if (bn_wexpand(a, 2) != NULL) {
- a->d[0] = lo;
- a->d[1] = hi;
- a->top = 2;
- a->neg = neg;
- bn_correct_top(a);
- return JNI_TRUE;
- }
- else return JNI_FALSE;
+ if (bn_wexpand(a, 2) != NULL) {
+ a->d[0] = lo;
+ a->d[1] = hi;
+ a->top = 2;
+ a->neg = neg;
+ bn_correct_top(a);
+ } else {
+ throwExceptionIfNecessary(env);
+ }
}
-static jboolean NativeBN_putLongInt(JNIEnv* env, jclass cls, BIGNUM* a, long long dw) {
- if (dw >= 0) return NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
- else return NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
+static void NativeBN_putLongInt(JNIEnv* env, jclass cls, jlong a, long long dw) {
+ if (dw >= 0) {
+ NativeBN_putULongInt(env, cls, a, dw, JNI_FALSE);
+ } else {
+ NativeBN_putULongInt(env, cls, a, -dw, JNI_TRUE);
+ }
}
-static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
- if (!oneValidHandle(env, a)) return -1;
- ScopedUtfChars chars(env, str);
- if (chars.c_str() == NULL) {
- return -1;
- }
- return BN_dec2bn(&a, chars.c_str());
+static int NativeBN_BN_dec2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
+ if (!oneValidHandle(env, a0)) return -1;
+ ScopedUtfChars chars(env, str);
+ if (chars.c_str() == NULL) {
+ return -1;
+ }
+ BIGNUM* a = toBigNum(a0);
+ int result = BN_dec2bn(&a, chars.c_str());
+ throwExceptionIfNecessary(env);
+ return result;
}
-static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, BIGNUM* a, jstring str) {
- if (!oneValidHandle(env, a)) return -1;
- ScopedUtfChars chars(env, str);
- if (chars.c_str() == NULL) {
- return -1;
- }
- return BN_hex2bn(&a, chars.c_str());
+static int NativeBN_BN_hex2bn(JNIEnv* env, jclass, jlong a0, jstring str) {
+ if (!oneValidHandle(env, a0)) return -1;
+ ScopedUtfChars chars(env, str);
+ if (chars.c_str() == NULL) {
+ return -1;
+ }
+ BIGNUM* a = toBigNum(a0);
+ int result = BN_hex2bn(&a, chars.c_str());
+ throwExceptionIfNecessary(env);
+ return result;
}
-static jboolean NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, BIGNUM* ret) {
- if (!oneValidHandle(env, ret)) return JNI_FALSE;
- ScopedByteArrayRO bytes(env, arr);
- if (bytes.get() == NULL) {
- return -1;
- }
- jboolean success = (BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, ret) != NULL);
- if (success && neg) {
- BN_set_negative(ret, 1);
- }
- return success;
+static void NativeBN_BN_bin2bn(JNIEnv* env, jclass, jbyteArray arr, int len, jboolean neg, jlong ret) {
+ if (!oneValidHandle(env, ret)) return;
+ ScopedByteArrayRO bytes(env, arr);
+ if (bytes.get() == NULL) {
+ return;
+ }
+ BN_bin2bn(reinterpret_cast<const unsigned char*>(bytes.get()), len, toBigNum(ret));
+ if (!throwExceptionIfNecessary(env) && neg) {
+ BN_set_negative(toBigNum(ret), true);
+ }
}
/**
- * public static native boolean litEndInts2bn(int[], int, int, int)
* Note:
* This procedure directly writes the internal representation of BIGNUMs.
* We do so as there is no direct interface based on Little Endian Integer Arrays.
* Also note that the same representation is used in the Cordoba Java Implementation of BigIntegers,
* whereof certain functionality is still being used.
*/
-static jboolean NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, BIGNUM* ret) {
- if (!oneValidHandle(env, ret)) return JNI_FALSE;
- bn_check_top(ret);
- if (len > 0) {
- ScopedIntArrayRO scopedArray(env, arr);
- if (scopedArray.get() == NULL) {
- return JNI_FALSE;
- }
-
- STATIC_ASSERT(sizeof(BN_ULONG) == sizeof(jint), BN_ULONG_not_32_bit);
- const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
- if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
- int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
- ret->top = len;
- ret->neg = neg;
- // need to call this due to clear byte at top if avoiding
- // having the top bit set (-ve number)
- // Basically get rid of top zero ints:
- bn_correct_top(ret);
- return JNI_TRUE;
- } else {
- return JNI_FALSE;
- }
- } else { // (len = 0) means value = 0 and sign will be 0, too.
- ret->top = 0;
- return JNI_TRUE;
+static void NativeBN_litEndInts2bn(JNIEnv* env, jclass, jintArray arr, int len, jboolean neg, jlong ret0) {
+ if (!oneValidHandle(env, ret0)) return;
+ BIGNUM* ret = toBigNum(ret0);
+ bn_check_top(ret);
+ if (len > 0) {
+ ScopedIntArrayRO scopedArray(env, arr);
+ if (scopedArray.get() == NULL) {
+ return;
}
+
+ STATIC_ASSERT(sizeof(BN_ULONG) == sizeof(jint), BN_ULONG_not_32_bit);
+ const BN_ULONG* tmpInts = reinterpret_cast<const BN_ULONG*>(scopedArray.get());
+ if ((tmpInts != NULL) && (bn_wexpand(ret, len) != NULL)) {
+ int i = len; do { i--; ret->d[i] = tmpInts[i]; } while (i > 0);
+ ret->top = len;
+ ret->neg = neg;
+ // need to call this due to clear byte at top if avoiding
+ // having the top bit set (-ve number)
+ // Basically get rid of top zero ints:
+ bn_correct_top(ret);
+ } else {
+ throwExceptionIfNecessary(env);
+ }
+ } else { // (len = 0) means value = 0 and sign will be 0, too.
+ ret->top = 0;
+ }
}
#define BYTES2INT(bytes, k) \
- ( (bytes[k + 3] & 0xFF) \
- | (bytes[k + 2] & 0xFF) << 8 \
- | (bytes[k + 1] & 0xFF) << 16 \
- | (bytes[k + 0] & 0xFF) << 24 )
+ ((bytes[k + 3] & 0xff) | (bytes[k + 2] & 0xff) << 8 | (bytes[k + 1] & 0xff) << 16 | (bytes[k + 0] & 0xff) << 24)
-static jboolean negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, BIGNUM* ret) {
- // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
- bn_check_top(ret);
- // FIXME: assert bytesLen > 0
- int intLen = (bytesLen + 3) / 4;
- int firstNonzeroDigit = -2;
- if (bn_wexpand(ret, intLen) != NULL) {
- BN_ULONG* d = ret->d;
- BN_ULONG di;
- ret->top = intLen;
- int highBytes = bytesLen % 4;
- int k = bytesLen;
- // Put bytes to the int array starting from the end of the byte array
- int i = 0;
+static void negBigEndianBytes2bn(JNIEnv*, jclass, const unsigned char* bytes, int bytesLen, jlong ret0) {
+ BIGNUM* ret = toBigNum(ret0);
+
+ // We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
+ bn_check_top(ret);
+ // FIXME: assert bytesLen > 0
+ int intLen = (bytesLen + 3) / 4;
+ int firstNonzeroDigit = -2;
+ if (bn_wexpand(ret, intLen) != NULL) {
+ BN_ULONG* d = ret->d;
+ BN_ULONG di;
+ ret->top = intLen;
+ int highBytes = bytesLen % 4;
+ int k = bytesLen;
+ // Put bytes to the int array starting from the end of the byte array
+ int i = 0;
+ while (k > highBytes) {
+ k -= 4;
+ di = BYTES2INT(bytes, k);
+ if (di != 0) {
+ d[i] = -di;
+ firstNonzeroDigit = i;
+ i++;
while (k > highBytes) {
- k -= 4;
- di = BYTES2INT(bytes, k);
- if (di != 0) {
- d[i] = -di;
- firstNonzeroDigit = i;
- i++;
- while (k > highBytes) {
- k -= 4;
- d[i] = ~BYTES2INT(bytes, k);
- i++;
- }
- break;
- } else {
- d[i] = 0;
- i++;
- }
+ k -= 4;
+ d[i] = ~BYTES2INT(bytes, k);
+ i++;
}
- if (highBytes != 0) {
- di = -1;
- // Put the first bytes in the highest element of the int array
- if (firstNonzeroDigit != -2) {
- for (k = 0; k < highBytes; k++) {
- di = (di << 8) | (bytes[k] & 0xFF);
- }
- d[i] = ~di;
- } else {
- for (k = 0; k < highBytes; k++) {
- di = (di << 8) | (bytes[k] & 0xFF);
- }
- d[i] = -di;
- }
- }
- return JNI_TRUE;
+ break;
+ } else {
+ d[i] = 0;
+ i++;
+ }
}
- else return JNI_FALSE;
+ if (highBytes != 0) {
+ di = -1;
+ // Put the first bytes in the highest element of the int array
+ if (firstNonzeroDigit != -2) {
+ for (k = 0; k < highBytes; k++) {
+ di = (di << 8) | (bytes[k] & 0xFF);
+ }
+ d[i] = ~di;
+ } else {
+ for (k = 0; k < highBytes; k++) {
+ di = (di << 8) | (bytes[k] & 0xFF);
+ }
+ d[i] = -di;
+ }
+ }
+ }
}
-static jboolean NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, BIGNUM* ret) {
- if (!oneValidHandle(env, ret)) return JNI_FALSE;
- ScopedByteArrayRO bytes(env, arr);
- if (bytes.get() == NULL) {
- return -1;
- }
- jboolean success;
- const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
- if ((bytes[0] & 0X80) == 0) { // Positive value!
- //
- // We can use the existing BN implementation for unsigned big endian bytes:
- //
- success = (BN_bin2bn(s, bytesLen, ret) != NULL);
- BN_set_negative(ret, JNI_FALSE);
- } else { // Negative value!
- //
- // We need to apply two's complement:
- //
- success = negBigEndianBytes2bn(env, cls, s, bytesLen, ret);
- BN_set_negative(ret, JNI_TRUE);
- }
- return success;
+static void NativeBN_twosComp2bn(JNIEnv* env, jclass cls, jbyteArray arr, int bytesLen, jlong ret0) {
+ if (!oneValidHandle(env, ret0)) return;
+ BIGNUM* ret = toBigNum(ret0);
+
+ ScopedByteArrayRO bytes(env, arr);
+ if (bytes.get() == NULL) {
+ return;
+ }
+ const unsigned char* s = reinterpret_cast<const unsigned char*>(bytes.get());
+ if ((bytes[0] & 0X80) == 0) { // Positive value!
+ //
+ // We can use the existing BN implementation for unsigned big endian bytes:
+ //
+ BN_bin2bn(s, bytesLen, ret);
+ BN_set_negative(ret, false);
+ } else { // Negative value!
+ //
+ // We need to apply two's complement:
+ //
+ negBigEndianBytes2bn(env, cls, s, bytesLen, ret0);
+ BN_set_negative(ret, true);
+ }
+ throwExceptionIfNecessary(env);
}
-static long long NativeBN_longInt(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return -1;
- bn_check_top(a);
- int intLen = a->top;
- BN_ULONG* d = a->d;
- switch (intLen) {
+static long long NativeBN_longInt(JNIEnv* env, jclass, jlong a0) {
+ if (!oneValidHandle(env, a0)) return -1;
+ BIGNUM* a = toBigNum(a0);
+ bn_check_top(a);
+ int intLen = a->top;
+ BN_ULONG* d = a->d;
+ switch (intLen) {
case 0:
- return 0;
+ return 0;
case 1:
- if (!a->neg) return d[0] & 0X00000000FFFFFFFFLL;
- else return -(d[0] & 0X00000000FFFFFFFFLL);
+ if (!a->neg) {
+ return d[0] & 0X00000000FFFFFFFFLL;
+ } else {
+ return -(d[0] & 0X00000000FFFFFFFFLL);
+ }
default:
- if (!a->neg) return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
- else return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
- }
+ if (!a->neg) {
+ return ((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL);
+ } else {
+ return -(((long long)d[1] << 32) | (d[0] & 0XFFFFFFFFLL));
+ }
+ }
}
static char* leadingZerosTrimmed(char* s) {
@@ -302,256 +325,250 @@
return p;
}
-static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return NULL;
- char* tmpStr;
- char* retStr;
- tmpStr = BN_bn2dec(a);
- if (tmpStr != NULL) {
- retStr = leadingZerosTrimmed(tmpStr);
- jstring returnJString = env->NewStringUTF(retStr);
- OPENSSL_free(tmpStr);
- return returnJString;
- }
- else return NULL;
+static jstring NativeBN_BN_bn2dec(JNIEnv* env, jclass, jlong a) {
+ if (!oneValidHandle(env, a)) return NULL;
+ char* tmpStr = BN_bn2dec(toBigNum(a));
+ if (tmpStr == NULL) {
+ return NULL;
+ }
+ char* retStr = leadingZerosTrimmed(tmpStr);
+ jstring returnJString = env->NewStringUTF(retStr);
+ OPENSSL_free(tmpStr);
+ return returnJString;
}
-static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return NULL;
- char* tmpStr;
- char* retStr;
- tmpStr = BN_bn2hex(a);
- if (tmpStr != NULL) {
- retStr = leadingZerosTrimmed(tmpStr);
- jstring returnJString = env->NewStringUTF(retStr);
- OPENSSL_free(tmpStr);
- return returnJString;
- }
- else return NULL;
+static jstring NativeBN_BN_bn2hex(JNIEnv* env, jclass, jlong a) {
+ if (!oneValidHandle(env, a)) return NULL;
+ char* tmpStr = BN_bn2hex(toBigNum(a));
+ if (tmpStr == NULL) {
+ return NULL;
+ }
+ char* retStr = leadingZerosTrimmed(tmpStr);
+ jstring returnJString = env->NewStringUTF(retStr);
+ OPENSSL_free(tmpStr);
+ return returnJString;
}
-static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return NULL;
- jbyteArray result = env->NewByteArray(BN_num_bytes(a));
- if (result == NULL) {
- return NULL;
- }
- ScopedByteArrayRW bytes(env, result);
- if (bytes.get() == NULL) {
- return NULL;
- }
- BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
- return result;
+static jbyteArray NativeBN_BN_bn2bin(JNIEnv* env, jclass, jlong a0) {
+ if (!oneValidHandle(env, a0)) return NULL;
+ BIGNUM* a = toBigNum(a0);
+ jbyteArray result = env->NewByteArray(BN_num_bytes(a));
+ if (result == NULL) {
+ return NULL;
+ }
+ ScopedByteArrayRW bytes(env, result);
+ if (bytes.get() == NULL) {
+ return NULL;
+ }
+ BN_bn2bin(a, reinterpret_cast<unsigned char*>(bytes.get()));
+ return result;
}
-static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return NULL;
- bn_check_top(a);
- int len = a->top;
- if (len == 0) {
- return NULL;
- }
- jintArray result = env->NewIntArray(len);
- if (result == NULL) {
- return NULL;
- }
- ScopedIntArrayRW ints(env, result);
- if (ints.get() == NULL) {
- return NULL;
- }
- BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
- if (ulongs == NULL) {
- return NULL;
- }
- int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
- return result;
+static jintArray NativeBN_bn2litEndInts(JNIEnv* env, jclass, jlong a0) {
+ if (!oneValidHandle(env, a0)) return NULL;
+ BIGNUM* a = toBigNum(a0);
+ bn_check_top(a);
+ int len = a->top;
+ if (len == 0) {
+ return NULL;
+ }
+ jintArray result = env->NewIntArray(len);
+ if (result == NULL) {
+ return NULL;
+ }
+ ScopedIntArrayRW ints(env, result);
+ if (ints.get() == NULL) {
+ return NULL;
+ }
+ BN_ULONG* ulongs = reinterpret_cast<BN_ULONG*>(ints.get());
+ if (ulongs == NULL) {
+ return NULL;
+ }
+ int i = len; do { i--; ulongs[i] = a->d[i]; } while (i > 0);
+ return result;
}
-static int NativeBN_sign(JNIEnv* env, jclass, BIGNUM* a) {
- if (!oneValidHandle(env, a)) return -2;
- if (BN_is_zero(a)) return 0;
- else if (BN_is_negative(a)) return -1;
- else return 1;
+static int NativeBN_sign(JNIEnv* env, jclass, jlong a) {
+ if (!oneValidHandle(env, a)) return -2;
+ if (BN_is_zero(toBigNum(a))) {
+ return 0;
+ } else if (BN_is_negative(toBigNum(a))) {
+ return -1;
+ }
+ return 1;
}
-static void NativeBN_BN_set_negative(JNIEnv* env, jclass, BIGNUM* b, int n) {
- if (!oneValidHandle(env, b)) return;
- BN_set_negative(b, n);
+static void NativeBN_BN_set_negative(JNIEnv* env, jclass, jlong b, int n) {
+ if (!oneValidHandle(env, b)) return;
+ BN_set_negative(toBigNum(b), n);
}
-static int NativeBN_bitLength(JNIEnv* env, jclass, BIGNUM* a) {
+static int NativeBN_bitLength(JNIEnv* env, jclass, jlong a0) {
// We rely on: (BN_BITS2 == 32), i.e. BN_ULONG is unsigned int and has 4 bytes:
//
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- bn_check_top(a);
- int intLen = a->top;
- if (intLen == 0) return 0;
- BN_ULONG* d = a->d;
- int i = intLen - 1;
- BN_ULONG msd = d[i]; // most significant digit
- if (a->neg) {
- // Handle negative values correctly:
- // i.e. decrement the msd if all other digits are 0:
- // while ((i > 0) && (d[i] != 0)) { i--; }
- do { i--; } while (!((i < 0) || (d[i] != 0)));
- if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
- }
- return (intLen - 1) * 32 + BN_num_bits_word(msd);
+ if (!oneValidHandle(env, a0)) return JNI_FALSE;
+ BIGNUM* a = toBigNum(a0);
+ bn_check_top(a);
+ int intLen = a->top;
+ if (intLen == 0) return 0;
+ BN_ULONG* d = a->d;
+ int i = intLen - 1;
+ BN_ULONG msd = d[i]; // most significant digit
+ if (a->neg) {
+ // Handle negative values correctly:
+ // i.e. decrement the msd if all other digits are 0:
+ // while ((i > 0) && (d[i] != 0)) { i--; }
+ do { i--; } while (!((i < 0) || (d[i] != 0)));
+ if (i < 0) msd--; // Only if all lower significant digits are 0 we decrement the most significant one.
+ }
+ return (intLen - 1) * 32 + BN_num_bits_word(msd);
}
-static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, BIGNUM* a, int n) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return (jboolean)BN_is_bit_set(a, n);
+static jboolean NativeBN_BN_is_bit_set(JNIEnv* env, jclass, jlong a, int n) {
+ if (!oneValidHandle(env, a)) return JNI_FALSE;
+ return BN_is_bit_set(toBigNum(a), n);
}
-static jboolean NativeBN_modifyBit(JNIEnv* env, jclass, BIGNUM* a, int n, int op) {
-// ALOGD("NativeBN_BN_modifyBit");
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- switch (op) {
- case 1: return BN_set_bit(a, n);
- case 0: return BN_clear_bit(a, n);
- case -1:
- if (BN_is_bit_set(a, n)) return BN_clear_bit(a, n);
- else return BN_set_bit(a, n);
- }
- return JNI_FALSE;
+static void NativeBN_BN_shift(JNIEnv* env, jclass, jlong r, jlong a, int n) {
+ if (!twoValidHandles(env, r, a)) return;
+ if (n >= 0) {
+ BN_lshift(toBigNum(r), toBigNum(a), n);
+ } else {
+ BN_rshift(toBigNum(r), toBigNum(a), -n);
+ }
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_shift(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, int n) {
- if (!twoValidHandles(env, r, a)) return JNI_FALSE;
- return (n >= 0) ? BN_lshift(r, a, n) : BN_rshift(r, a, -n);
+static void NativeBN_BN_add_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+ if (!oneValidHandle(env, a)) return;
+ BN_add_word(toBigNum(a), w);
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_add_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_add_word(a, w);
+static void NativeBN_BN_mul_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+ if (!oneValidHandle(env, a)) return;
+ BN_mul_word(toBigNum(a), w);
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_sub_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_sub_word(a, w);
+static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, jlong a, BN_ULONG w) {
+ if (!oneValidHandle(env, a)) return 0;
+ int result = BN_mod_word(toBigNum(a), w);
+ throwExceptionIfNecessary(env);
+ return result;
}
-static jboolean NativeBN_BN_mul_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_mul_word(a, w);
+static void NativeBN_BN_add(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+ if (!threeValidHandles(env, r, a, b)) return;
+ BN_add(toBigNum(r), toBigNum(a), toBigNum(b));
+ throwExceptionIfNecessary(env);
}
-static BN_ULONG NativeBN_BN_div_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_div_word(a, w);
+static void NativeBN_BN_sub(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+ if (!threeValidHandles(env, r, a, b)) return;
+ BN_sub(toBigNum(r), toBigNum(a), toBigNum(b));
+ throwExceptionIfNecessary(env);
}
-static BN_ULONG NativeBN_BN_mod_word(JNIEnv* env, jclass, BIGNUM* a, BN_ULONG w) {
- if (!oneValidHandle(env, a)) return JNI_FALSE;
- return BN_mod_word(a, w);
+static void NativeBN_BN_gcd(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+ if (!threeValidHandles(env, r, a, b)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_gcd(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_add(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
- if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
- return BN_add(r, a, b);
+static void NativeBN_BN_mul(JNIEnv* env, jclass, jlong r, jlong a, jlong b) {
+ if (!threeValidHandles(env, r, a, b)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_mul(toBigNum(r), toBigNum(a), toBigNum(b), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_sub(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
- if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
- return BN_sub(r, a, b);
+static void NativeBN_BN_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p) {
+ if (!threeValidHandles(env, r, a, p)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_exp(toBigNum(r), toBigNum(a), toBigNum(p), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_gcd(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
- if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_gcd(r, a, b, ctx.get());
+static void NativeBN_BN_div(JNIEnv* env, jclass, jlong dv, jlong rem, jlong m, jlong d) {
+ if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_div(toBigNum(dv), toBigNum(rem), toBigNum(m), toBigNum(d), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_mul(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* b) {
- if (!threeValidHandles(env, r, a, b)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_mul(r, a, b, ctx.get());
+static void NativeBN_BN_nnmod(JNIEnv* env, jclass, jlong r, jlong a, jlong m) {
+ if (!threeValidHandles(env, r, a, m)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_nnmod(toBigNum(r), toBigNum(a), toBigNum(m), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p) {
- if (!threeValidHandles(env, r, a, p)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_exp(r, a, p, ctx.get());
+static void NativeBN_BN_mod_exp(JNIEnv* env, jclass, jlong r, jlong a, jlong p, jlong m) {
+ if (!fourValidHandles(env, r, a, p, m)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_mod_exp(toBigNum(r), toBigNum(a), toBigNum(p), toBigNum(m), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_div(JNIEnv* env, jclass, BIGNUM* dv, BIGNUM* rem, BIGNUM* m, BIGNUM* d) {
- if (!fourValidHandles(env, (rem ? rem : dv), (dv ? dv : rem), m, d)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_div(dv, rem, m, d, ctx.get());
+static void NativeBN_BN_mod_inverse(JNIEnv* env, jclass, jlong ret, jlong a, jlong n) {
+ if (!threeValidHandles(env, ret, a, n)) return;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ BN_mod_inverse(toBigNum(ret), toBigNum(a), toBigNum(n), ctx.get());
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_nnmod(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* m) {
- if (!threeValidHandles(env, r, a, m)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_nnmod(r, a, m, ctx.get());
+static void NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, jlong ret, int bits,
+ jboolean safe, jlong add, jlong rem, jlong cb) {
+ if (!oneValidHandle(env, ret)) return;
+ BN_generate_prime_ex(toBigNum(ret), bits, safe, toBigNum(add), toBigNum(rem),
+ reinterpret_cast<BN_GENCB*>(cb));
+ throwExceptionIfNecessary(env);
}
-static jboolean NativeBN_BN_mod_exp(JNIEnv* env, jclass, BIGNUM* r, BIGNUM* a, BIGNUM* p, BIGNUM* m) {
- if (!fourValidHandles(env, r, a, p, m)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_mod_exp(r, a, p, m, ctx.get());
-}
-
-static jboolean NativeBN_BN_mod_inverse(JNIEnv* env, jclass, BIGNUM* ret, BIGNUM* a, BIGNUM* n) {
- if (!threeValidHandles(env, ret, a, n)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return (BN_mod_inverse(ret, a, n, ctx.get()) != NULL);
-}
-
-static jboolean NativeBN_BN_generate_prime_ex(JNIEnv* env, jclass, BIGNUM* ret, int bits, jboolean safe,
- BIGNUM* add, BIGNUM* rem, jint cb) {
- if (!oneValidHandle(env, ret)) return JNI_FALSE;
- return BN_generate_prime_ex(ret, bits, safe, add, rem, reinterpret_cast<BN_GENCB*>(cb));
-}
-
-static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, BIGNUM* p, int nchecks, jint cb) {
- if (!oneValidHandle(env, p)) return JNI_FALSE;
- Unique_BN_CTX ctx(BN_CTX_new());
- return BN_is_prime_ex(p, nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
+static jboolean NativeBN_BN_is_prime_ex(JNIEnv* env, jclass, jlong p, int nchecks, jlong cb) {
+ if (!oneValidHandle(env, p)) return JNI_FALSE;
+ Unique_BN_CTX ctx(BN_CTX_new());
+ return BN_is_prime_ex(toBigNum(p), nchecks, ctx.get(), reinterpret_cast<BN_GENCB*>(cb));
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeBN, BN_add, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_add_word, "(II)Z"),
- NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZI)Z"),
- NATIVE_METHOD(NativeBN, BN_bn2bin, "(I)[B"),
- NATIVE_METHOD(NativeBN, BN_bn2dec, "(I)Ljava/lang/String;"),
- NATIVE_METHOD(NativeBN, BN_bn2hex, "(I)Ljava/lang/String;"),
- NATIVE_METHOD(NativeBN, BN_cmp, "(II)I"),
- NATIVE_METHOD(NativeBN, BN_copy, "(II)Z"),
- NATIVE_METHOD(NativeBN, BN_dec2bn, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBN, BN_div, "(IIII)Z"),
- NATIVE_METHOD(NativeBN, BN_div_word, "(II)I"),
- NATIVE_METHOD(NativeBN, BN_exp, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_free, "(I)V"),
- NATIVE_METHOD(NativeBN, BN_gcd, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(IIZIII)Z"),
- NATIVE_METHOD(NativeBN, BN_hex2bn, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBN, BN_is_bit_set, "(II)Z"),
- NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_mod_exp, "(IIII)Z"),
- NATIVE_METHOD(NativeBN, BN_mod_inverse, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_mod_word, "(II)I"),
- NATIVE_METHOD(NativeBN, BN_mul, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_mul_word, "(II)Z"),
- NATIVE_METHOD(NativeBN, BN_new, "()I"),
- NATIVE_METHOD(NativeBN, BN_nnmod, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_set_negative, "(II)V"),
- NATIVE_METHOD(NativeBN, BN_shift, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_sub, "(III)Z"),
- NATIVE_METHOD(NativeBN, BN_sub_word, "(II)Z"),
- NATIVE_METHOD(NativeBN, ERR_error_string, "(I)Ljava/lang/String;"),
- NATIVE_METHOD(NativeBN, ERR_get_error, "()I"),
- NATIVE_METHOD(NativeBN, bitLength, "(I)I"),
- NATIVE_METHOD(NativeBN, bn2litEndInts, "(I)[I"),
- NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZI)Z"),
- NATIVE_METHOD(NativeBN, longInt, "(I)J"),
- NATIVE_METHOD(NativeBN, modifyBit, "(III)Z"),
- NATIVE_METHOD(NativeBN, putLongInt, "(IJ)Z"),
- NATIVE_METHOD(NativeBN, putULongInt, "(IJZ)Z"),
- NATIVE_METHOD(NativeBN, sign, "(I)I"),
- NATIVE_METHOD(NativeBN, twosComp2bn, "([BII)Z"),
+ NATIVE_METHOD(NativeBN, BN_add, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_add_word, "(JI)V"),
+ NATIVE_METHOD(NativeBN, BN_bin2bn, "([BIZJ)V"),
+ NATIVE_METHOD(NativeBN, BN_bn2bin, "(J)[B"),
+ NATIVE_METHOD(NativeBN, BN_bn2dec, "(J)Ljava/lang/String;"),
+ NATIVE_METHOD(NativeBN, BN_bn2hex, "(J)Ljava/lang/String;"),
+ NATIVE_METHOD(NativeBN, BN_cmp, "(JJ)I"),
+ NATIVE_METHOD(NativeBN, BN_copy, "(JJ)V"),
+ NATIVE_METHOD(NativeBN, BN_dec2bn, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBN, BN_div, "(JJJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_exp, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_free, "(J)V"),
+ NATIVE_METHOD(NativeBN, BN_gcd, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_generate_prime_ex, "(JIZJJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_hex2bn, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBN, BN_is_bit_set, "(JI)Z"),
+ NATIVE_METHOD(NativeBN, BN_is_prime_ex, "(JIJ)Z"),
+ NATIVE_METHOD(NativeBN, BN_mod_exp, "(JJJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_mod_inverse, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_mod_word, "(JI)I"),
+ NATIVE_METHOD(NativeBN, BN_mul, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_mul_word, "(JI)V"),
+ NATIVE_METHOD(NativeBN, BN_new, "()J"),
+ NATIVE_METHOD(NativeBN, BN_nnmod, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, BN_set_negative, "(JI)V"),
+ NATIVE_METHOD(NativeBN, BN_shift, "(JJI)V"),
+ NATIVE_METHOD(NativeBN, BN_sub, "(JJJ)V"),
+ NATIVE_METHOD(NativeBN, bitLength, "(J)I"),
+ NATIVE_METHOD(NativeBN, bn2litEndInts, "(J)[I"),
+ NATIVE_METHOD(NativeBN, litEndInts2bn, "([IIZJ)V"),
+ NATIVE_METHOD(NativeBN, longInt, "(J)J"),
+ NATIVE_METHOD(NativeBN, putLongInt, "(JJ)V"),
+ NATIVE_METHOD(NativeBN, putULongInt, "(JJZ)V"),
+ NATIVE_METHOD(NativeBN, sign, "(J)I"),
+ NATIVE_METHOD(NativeBN, twosComp2bn, "([BIJ)V"),
};
void register_java_math_NativeBN(JNIEnv* env) {
jniRegisterNativeMethods(env, "java/math/NativeBN", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
index e034c37..bb05193 100644
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
@@ -21,7 +21,6 @@
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedJavaUnicodeString.h"
-#include "ScopedStringChars.h"
#include "unicode/alphaindex.h"
#include "unicode/uniset.h"
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
new file mode 100644
index 0000000..65ace4e
--- /dev/null
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "DateIntervalFormat"
+
+#include "IcuUtilities.h"
+#include "JniConstants.h"
+#include "ScopedJavaUnicodeString.h"
+#include "UniquePtr.h"
+#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) {
+ Locale locale = getLocale(env, javaLocaleName);
+
+ ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
+ if (!skeletonHolder.valid()) {
+ return NULL;
+ }
+
+ ScopedJavaUnicodeString tzNameHolder(env, javaTzName);
+ if (!tzNameHolder.valid()) {
+ return NULL;
+ }
+
+ 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()));
+
+ DateInterval date_interval(fromDate, toDate);
+
+ UnicodeString result;
+ FieldPosition pos = 0;
+ formatter->format(&date_interval, result, pos, status);
+ if (maybeThrowIcuException(env, "DateIntervalFormat::format", status)) {
+ return NULL;
+ }
+
+ return env->NewString(result.getBuffer(), result.length());
+}
+
+static JNINativeMethod gMethods[] = {
+ NATIVE_METHOD(DateIntervalFormat, formatDateInterval, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JJ)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 53a1241..40d6e04 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -394,9 +394,10 @@
}
void Up() {
- locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
if (locale_name_length_ == 0) {
has_next_ = false;
+ } else {
+ locale_name_length_ = uloc_getParent(locale_name_, locale_name_, sizeof(locale_name_), &status_);
}
}
@@ -466,15 +467,7 @@
if (U_FAILURE(status)) {
return false;
}
- ScopedResourceBundle calendar(ures_getByKey(root.get(), "calendar", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle gregorian(ures_getByKey(calendar.get(), "gregorian", NULL, &status));
- if (U_FAILURE(status)) {
- return false;
- }
- ScopedResourceBundle fields(ures_getByKey(gregorian.get(), "fields", NULL, &status));
+ ScopedResourceBundle fields(ures_getByKey(root.get(), "fields", NULL, &status));
if (U_FAILURE(status)) {
return false;
}
@@ -699,7 +692,7 @@
return result;
}
-static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaPattern, jstring javaLocaleName) {
+static jstring ICU_getBestDateTimePattern(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
Locale locale = getLocale(env, javaLocaleName);
UErrorCode status = U_ZERO_ERROR;
DateTimePatternGenerator* generator = DateTimePatternGenerator::createInstance(locale, status);
@@ -707,11 +700,11 @@
return NULL;
}
- ScopedJavaUnicodeString patternHolder(env, javaPattern);
- if (!patternHolder.valid()) {
+ ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
+ if (!skeletonHolder.valid()) {
return NULL;
}
- UnicodeString result(generator->getBestPattern(patternHolder.unicodeString(), status));
+ UnicodeString result(generator->getBestPattern(skeletonHolder.unicodeString(), status));
if (maybeThrowIcuException(env, "DateTimePatternGenerator::getBestPattern", status)) {
return NULL;
}
diff --git a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
index c025a60..5d715c9 100644
--- a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
+++ b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
@@ -27,7 +27,7 @@
// ICU documentation: http://icu-project.org/apiref/icu4c/classBreakIterator.html
-static BreakIterator* toBreakIterator(jint address) {
+static BreakIterator* toBreakIterator(jlong address) {
return reinterpret_cast<BreakIterator*>(static_cast<uintptr_t>(address));
}
@@ -39,7 +39,7 @@
*/
class BreakIteratorAccessor {
public:
- BreakIteratorAccessor(JNIEnv* env, jint address, jstring javaInput, bool reset) {
+ BreakIteratorAccessor(JNIEnv* env, jlong address, jstring javaInput, bool reset) {
init(env, address);
mJavaInput = javaInput;
@@ -64,7 +64,7 @@
}
}
- BreakIteratorAccessor(JNIEnv* env, jint address) {
+ BreakIteratorAccessor(JNIEnv* env, jlong address) {
init(env, address);
}
@@ -85,7 +85,7 @@
}
private:
- void init(JNIEnv* env, jint address) {
+ void init(JNIEnv* env, jlong address) {
mEnv = env;
mJavaInput = NULL;
mBreakIterator = toBreakIterator(address);
@@ -119,26 +119,26 @@
} \
return reinterpret_cast<uintptr_t>(it)
-static jint NativeBreakIterator_cloneImpl(JNIEnv* env, jclass, jint address) {
+static jint NativeBreakIterator_cloneImpl(JNIEnv* env, jclass, jlong address) {
BreakIteratorAccessor it(env, address);
return reinterpret_cast<uintptr_t>(it->clone());
}
-static void NativeBreakIterator_closeImpl(JNIEnv*, jclass, jint address) {
+static void NativeBreakIterator_closeImpl(JNIEnv*, jclass, jlong address) {
delete toBreakIterator(address);
}
-static jint NativeBreakIterator_currentImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_currentImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->current();
}
-static jint NativeBreakIterator_firstImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_firstImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->first();
}
-static jint NativeBreakIterator_followingImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jint NativeBreakIterator_followingImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->following(offset);
}
@@ -159,17 +159,17 @@
MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createWordInstance);
}
-static jboolean NativeBreakIterator_isBoundaryImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jboolean NativeBreakIterator_isBoundaryImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->isBoundary(offset);
}
-static jint NativeBreakIterator_lastImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_lastImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->last();
}
-static jint NativeBreakIterator_nextImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint n) {
+static jint NativeBreakIterator_nextImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint n) {
BreakIteratorAccessor it(env, address, javaInput, false);
if (n < 0) {
while (n++ < -1) {
@@ -187,36 +187,36 @@
return -1;
}
-static jint NativeBreakIterator_precedingImpl(JNIEnv* env, jclass, jint address, jstring javaInput, jint offset) {
+static jint NativeBreakIterator_precedingImpl(JNIEnv* env, jclass, jlong address, jstring javaInput, jint offset) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->preceding(offset);
}
-static jint NativeBreakIterator_previousImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static jint NativeBreakIterator_previousImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
BreakIteratorAccessor it(env, address, javaInput, false);
return it->previous();
}
-static void NativeBreakIterator_setTextImpl(JNIEnv* env, jclass, jint address, jstring javaInput) {
+static void NativeBreakIterator_setTextImpl(JNIEnv* env, jclass, jlong address, jstring javaInput) {
BreakIteratorAccessor it(env, address, javaInput, true);
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeBreakIterator, cloneImpl, "(I)I"),
- NATIVE_METHOD(NativeBreakIterator, closeImpl, "(I)V"),
- NATIVE_METHOD(NativeBreakIterator, currentImpl, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, firstImpl, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, followingImpl, "(ILjava/lang/String;I)I"),
- NATIVE_METHOD(NativeBreakIterator, getCharacterInstanceImpl, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, getLineInstanceImpl, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, getSentenceInstanceImpl, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, getWordInstanceImpl, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, isBoundaryImpl, "(ILjava/lang/String;I)Z"),
- NATIVE_METHOD(NativeBreakIterator, lastImpl, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, nextImpl, "(ILjava/lang/String;I)I"),
- NATIVE_METHOD(NativeBreakIterator, precedingImpl, "(ILjava/lang/String;I)I"),
- NATIVE_METHOD(NativeBreakIterator, previousImpl, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeBreakIterator, setTextImpl, "(ILjava/lang/String;)V"),
+ NATIVE_METHOD(NativeBreakIterator, cloneImpl, "(J)J"),
+ NATIVE_METHOD(NativeBreakIterator, closeImpl, "(J)V"),
+ NATIVE_METHOD(NativeBreakIterator, currentImpl, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBreakIterator, firstImpl, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBreakIterator, followingImpl, "(JLjava/lang/String;I)I"),
+ NATIVE_METHOD(NativeBreakIterator, getCharacterInstanceImpl, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativeBreakIterator, getLineInstanceImpl, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativeBreakIterator, getSentenceInstanceImpl, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativeBreakIterator, getWordInstanceImpl, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativeBreakIterator, isBoundaryImpl, "(JLjava/lang/String;I)Z"),
+ NATIVE_METHOD(NativeBreakIterator, lastImpl, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBreakIterator, nextImpl, "(JLjava/lang/String;I)I"),
+ NATIVE_METHOD(NativeBreakIterator, precedingImpl, "(JLjava/lang/String;I)I"),
+ NATIVE_METHOD(NativeBreakIterator, previousImpl, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeBreakIterator, setTextImpl, "(JLjava/lang/String;)V"),
};
void register_libcore_icu_NativeBreakIterator(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/icu/NativeBreakIterator", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 98a78ea..9ac7745 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -20,23 +20,23 @@
#include "unicode/ucol.h"
#include "unicode/ucoleitr.h"
-static UCollator* toCollator(jint address) {
+static UCollator* toCollator(jlong address) {
return reinterpret_cast<UCollator*>(static_cast<uintptr_t>(address));
}
-static UCollationElements* toCollationElements(jint address) {
+static UCollationElements* toCollationElements(jlong address) {
return reinterpret_cast<UCollationElements*>(static_cast<uintptr_t>(address));
}
-static void NativeCollation_closeCollator(JNIEnv*, jclass, jint address) {
+static void NativeCollation_closeCollator(JNIEnv*, jclass, jlong address) {
ucol_close(toCollator(address));
}
-static void NativeCollation_closeElements(JNIEnv*, jclass, jint address) {
+static void NativeCollation_closeElements(JNIEnv*, jclass, jlong address) {
ucol_closeElements(toCollationElements(address));
}
-static jint NativeCollation_compare(JNIEnv* env, jclass, jint address, jstring javaLhs, jstring javaRhs) {
+static jint NativeCollation_compare(JNIEnv* env, jclass, jlong address, jstring javaLhs, jstring javaRhs) {
ScopedStringChars lhs(env, javaLhs);
if (lhs.get() == NULL) {
return 0;
@@ -48,14 +48,14 @@
return ucol_strcoll(toCollator(address), lhs.get(), lhs.size(), rhs.get(), rhs.size());
}
-static jint NativeCollation_getAttribute(JNIEnv* env, jclass, jint address, jint type) {
+static jint NativeCollation_getAttribute(JNIEnv* env, jclass, jlong address, jint type) {
UErrorCode status = U_ZERO_ERROR;
jint result = ucol_getAttribute(toCollator(address), (UColAttribute) type, &status);
maybeThrowIcuException(env, "ucol_getAttribute", status);
return result;
}
-static jint NativeCollation_getCollationElementIterator(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static jlong NativeCollation_getCollationElementIterator(JNIEnv* env, jclass, jlong address, jstring javaSource) {
ScopedStringChars source(env, javaSource);
if (source.get() == NULL) {
return -1;
@@ -63,24 +63,24 @@
UErrorCode status = U_ZERO_ERROR;
UCollationElements* result = ucol_openElements(toCollator(address), source.get(), source.size(), &status);
maybeThrowIcuException(env, "ucol_openElements", status);
- return static_cast<jint>(reinterpret_cast<uintptr_t>(result));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(result));
}
-static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jint address, jint order) {
+static jint NativeCollation_getMaxExpansion(JNIEnv*, jclass, jlong address, jint order) {
return ucol_getMaxExpansion(toCollationElements(address), order);
}
-static jint NativeCollation_getOffset(JNIEnv*, jclass, jint address) {
+static jint NativeCollation_getOffset(JNIEnv*, jclass, jlong address) {
return ucol_getOffset(toCollationElements(address));
}
-static jstring NativeCollation_getRules(JNIEnv* env, jclass, jint address) {
+static jstring NativeCollation_getRules(JNIEnv* env, jclass, jlong address) {
int32_t length = 0;
const UChar* rules = ucol_getRules(toCollator(address), &length);
return env->NewString(rules, length);
}
-static jbyteArray NativeCollation_getSortKey(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static jbyteArray NativeCollation_getSortKey(JNIEnv* env, jclass, jlong address, jstring javaSource) {
ScopedStringChars source(env, javaSource);
if (source.get() == NULL) {
return NULL;
@@ -104,14 +104,14 @@
return result;
}
-static jint NativeCollation_next(JNIEnv* env, jclass, jint address) {
+static jint NativeCollation_next(JNIEnv* env, jclass, jlong address) {
UErrorCode status = U_ZERO_ERROR;
jint result = ucol_next(toCollationElements(address), &status);
maybeThrowIcuException(env, "ucol_next", status);
return result;
}
-static jint NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
+static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
ScopedUtfChars localeChars(env, localeName);
if (localeChars.c_str() == NULL) {
return 0;
@@ -119,10 +119,10 @@
UErrorCode status = U_ZERO_ERROR;
UCollator* c = ucol_open(localeChars.c_str(), &status);
maybeThrowIcuException(env, "ucol_open", status);
- return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
}
-static jint NativeCollation_openCollatorFromRules(JNIEnv* env, jclass, jstring javaRules, jint mode, jint strength) {
+static jlong NativeCollation_openCollatorFromRules(JNIEnv* env, jclass, jstring javaRules, jint mode, jint strength) {
ScopedStringChars rules(env, javaRules);
if (rules.get() == NULL) {
return -1;
@@ -131,41 +131,41 @@
UCollator* c = ucol_openRules(rules.get(), rules.size(),
UColAttributeValue(mode), UCollationStrength(strength), NULL, &status);
maybeThrowIcuException(env, "ucol_openRules", status);
- return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
}
-static jint NativeCollation_previous(JNIEnv* env, jclass, jint address) {
+static jint NativeCollation_previous(JNIEnv* env, jclass, jlong address) {
UErrorCode status = U_ZERO_ERROR;
jint result = ucol_previous(toCollationElements(address), &status);
maybeThrowIcuException(env, "ucol_previous", status);
return result;
}
-static void NativeCollation_reset(JNIEnv*, jclass, jint address) {
+static void NativeCollation_reset(JNIEnv*, jclass, jlong address) {
ucol_reset(toCollationElements(address));
}
-static jint NativeCollation_safeClone(JNIEnv* env, jclass, jint address) {
+static jlong NativeCollation_safeClone(JNIEnv* env, jclass, jlong address) {
UErrorCode status = U_ZERO_ERROR;
jint bufferSize = U_COL_SAFECLONE_BUFFERSIZE;
UCollator* c = ucol_safeClone(toCollator(address), NULL, &bufferSize, &status);
maybeThrowIcuException(env, "ucol_safeClone", status);
- return static_cast<jint>(reinterpret_cast<uintptr_t>(c));
+ return static_cast<jlong>(reinterpret_cast<uintptr_t>(c));
}
-static void NativeCollation_setAttribute(JNIEnv* env, jclass, jint address, jint type, jint value) {
+static void NativeCollation_setAttribute(JNIEnv* env, jclass, jlong address, jint type, jint value) {
UErrorCode status = U_ZERO_ERROR;
ucol_setAttribute(toCollator(address), (UColAttribute)type, (UColAttributeValue)value, &status);
maybeThrowIcuException(env, "ucol_setAttribute", status);
}
-static void NativeCollation_setOffset(JNIEnv* env, jclass, jint address, jint offset) {
+static void NativeCollation_setOffset(JNIEnv* env, jclass, jlong address, jint offset) {
UErrorCode status = U_ZERO_ERROR;
ucol_setOffset(toCollationElements(address), offset, &status);
maybeThrowIcuException(env, "ucol_setOffset", status);
}
-static void NativeCollation_setText(JNIEnv* env, jclass, jint address, jstring javaSource) {
+static void NativeCollation_setText(JNIEnv* env, jclass, jlong address, jstring javaSource) {
ScopedStringChars source(env, javaSource);
if (source.get() == NULL) {
return;
@@ -176,24 +176,24 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeCollation, closeCollator, "(I)V"),
- NATIVE_METHOD(NativeCollation, closeElements, "(I)V"),
- NATIVE_METHOD(NativeCollation, compare, "(ILjava/lang/String;Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeCollation, getAttribute, "(II)I"),
- NATIVE_METHOD(NativeCollation, getCollationElementIterator, "(ILjava/lang/String;)I"),
- NATIVE_METHOD(NativeCollation, getMaxExpansion, "(II)I"),
- NATIVE_METHOD(NativeCollation, getOffset, "(I)I"),
- NATIVE_METHOD(NativeCollation, getRules, "(I)Ljava/lang/String;"),
- NATIVE_METHOD(NativeCollation, getSortKey, "(ILjava/lang/String;)[B"),
- NATIVE_METHOD(NativeCollation, next, "(I)I"),
- NATIVE_METHOD(NativeCollation, openCollator, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativeCollation, openCollatorFromRules, "(Ljava/lang/String;II)I"),
- NATIVE_METHOD(NativeCollation, previous, "(I)I"),
- NATIVE_METHOD(NativeCollation, reset, "(I)V"),
- NATIVE_METHOD(NativeCollation, safeClone, "(I)I"),
- NATIVE_METHOD(NativeCollation, setAttribute, "(III)V"),
- NATIVE_METHOD(NativeCollation, setOffset, "(II)V"),
- NATIVE_METHOD(NativeCollation, setText, "(ILjava/lang/String;)V"),
+ NATIVE_METHOD(NativeCollation, closeCollator, "(J)V"),
+ NATIVE_METHOD(NativeCollation, closeElements, "(J)V"),
+ NATIVE_METHOD(NativeCollation, compare, "(JLjava/lang/String;Ljava/lang/String;)I"),
+ NATIVE_METHOD(NativeCollation, getAttribute, "(JI)I"),
+ NATIVE_METHOD(NativeCollation, getCollationElementIterator, "(JLjava/lang/String;)I"),
+ NATIVE_METHOD(NativeCollation, getMaxExpansion, "(JI)I"),
+ NATIVE_METHOD(NativeCollation, getOffset, "(J)I"),
+ NATIVE_METHOD(NativeCollation, getRules, "(J)Ljava/lang/String;"),
+ NATIVE_METHOD(NativeCollation, getSortKey, "(JLjava/lang/String;)[B"),
+ NATIVE_METHOD(NativeCollation, next, "(J)I"),
+ NATIVE_METHOD(NativeCollation, openCollator, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativeCollation, openCollatorFromRules, "(Ljava/lang/String;II)J"),
+ NATIVE_METHOD(NativeCollation, previous, "(J)I"),
+ NATIVE_METHOD(NativeCollation, reset, "(J)V"),
+ NATIVE_METHOD(NativeCollation, safeClone, "(J)J"),
+ NATIVE_METHOD(NativeCollation, setAttribute, "(JII)V"),
+ NATIVE_METHOD(NativeCollation, setOffset, "(JI)V"),
+ NATIVE_METHOD(NativeCollation, setText, "(JLjava/lang/String;)V"),
};
void register_libcore_icu_NativeCollation(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/icu/NativeCollation", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_NativeConverter.cpp b/luni/src/main/native/libcore_icu_NativeConverter.cpp
index 24dfa6f..fae56b7 100644
--- a/luni/src/main/native/libcore_icu_NativeConverter.cpp
+++ b/luni/src/main/native/libcore_icu_NativeConverter.cpp
@@ -230,28 +230,6 @@
return (cnv != NULL) ? ((ucnv_getMaxCharSize(cnv) + ucnv_getMinCharSize(cnv)) / 2.0) : -1;
}
-static jboolean NativeConverter_canEncode(JNIEnv*, jclass, jlong address, jint codeUnit) {
- UErrorCode errorCode = U_ZERO_ERROR;
- UConverter* cnv = toUConverter(address);
- if (cnv == NULL) {
- return JNI_FALSE;
- }
-
- UChar srcBuffer[3];
- const UChar* src = &srcBuffer[0];
- const UChar* srcLimit = (codeUnit < 0x10000) ? &src[1] : &src[2];
-
- char dstBuffer[5];
- char* dst = &dstBuffer[0];
- const char* dstLimit = &dstBuffer[4];
-
- int i = 0;
- UTF_APPEND_CHAR(&srcBuffer[0], i, 2, codeUnit);
-
- ucnv_fromUnicode(cnv, &dst, dstLimit, &src, srcLimit, NULL, TRUE, &errorCode);
- return U_SUCCESS(errorCode);
-}
-
/*
* 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.
@@ -620,7 +598,6 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativeConverter, canEncode, "(JI)Z"),
NATIVE_METHOD(NativeConverter, charsetForName, "(Ljava/lang/String;)Ljava/nio/charset/Charset;"),
NATIVE_METHOD(NativeConverter, closeConverter, "(J)V"),
NATIVE_METHOD(NativeConverter, contains, "(Ljava/lang/String;Ljava/lang/String;)Z"),
diff --git a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
index efed954..88e6780 100644
--- a/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_NativeDecimalFormat.cpp
@@ -343,7 +343,7 @@
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(NativeDecimalFormat, applyPatternImpl, "(JZLjava/lang/String;)V"),
- NATIVE_METHOD(NativeDecimalFormat, cloneImpl, "(J)I"),
+ NATIVE_METHOD(NativeDecimalFormat, cloneImpl, "(J)J"),
NATIVE_METHOD(NativeDecimalFormat, close, "(J)V"),
NATIVE_METHOD(NativeDecimalFormat, formatDouble, "(JDLlibcore/icu/NativeDecimalFormat$FieldPositionIterator;)[C"),
NATIVE_METHOD(NativeDecimalFormat, formatLong, "(JJLlibcore/icu/NativeDecimalFormat$FieldPositionIterator;)[C"),
diff --git a/luni/src/main/native/libcore_icu_NativePluralRules.cpp b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
index 571ba6d..8910a8c 100644
--- a/luni/src/main/native/libcore_icu_NativePluralRules.cpp
+++ b/luni/src/main/native/libcore_icu_NativePluralRules.cpp
@@ -25,15 +25,15 @@
#include <string>
-static PluralRules* toPluralRules(jint address) {
+static PluralRules* toPluralRules(jlong address) {
return reinterpret_cast<PluralRules*>(static_cast<uintptr_t>(address));
}
-static void NativePluralRules_finalizeImpl(JNIEnv*, jclass, jint address) {
+static void NativePluralRules_finalizeImpl(JNIEnv*, jclass, jlong address) {
delete toPluralRules(address);
}
-static jint NativePluralRules_forLocaleImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
+static jlong NativePluralRules_forLocaleImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
// The icu4c PluralRules returns a "other: n" default rule for the deprecated locales Java uses.
// Work around this by translating back to the current language codes.
std::string localeName(ScopedUtfChars(env, javaLocaleName).c_str());
@@ -55,7 +55,7 @@
return reinterpret_cast<uintptr_t>(result);
}
-static jint NativePluralRules_quantityForIntImpl(JNIEnv*, jclass, jint address, jint value) {
+static jint NativePluralRules_quantityForIntImpl(JNIEnv*, jclass, jlong address, jint value) {
UnicodeString keyword = toPluralRules(address)->select(value);
if (keyword == "zero") {
return 0;
@@ -73,9 +73,9 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(NativePluralRules, finalizeImpl, "(I)V"),
- NATIVE_METHOD(NativePluralRules, forLocaleImpl, "(Ljava/lang/String;)I"),
- NATIVE_METHOD(NativePluralRules, quantityForIntImpl, "(II)I"),
+ NATIVE_METHOD(NativePluralRules, finalizeImpl, "(J)V"),
+ NATIVE_METHOD(NativePluralRules, forLocaleImpl, "(Ljava/lang/String;)J"),
+ NATIVE_METHOD(NativePluralRules, quantityForIntImpl, "(JI)I"),
};
void register_libcore_icu_NativePluralRules(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/icu/NativePluralRules", gMethods, NELEM(gMethods));
diff --git a/luni/src/main/native/libcore_icu_Transliterator.cpp b/luni/src/main/native/libcore_icu_Transliterator.cpp
index 282e642..f2a54cb 100644
--- a/luni/src/main/native/libcore_icu_Transliterator.cpp
+++ b/luni/src/main/native/libcore_icu_Transliterator.cpp
@@ -21,7 +21,6 @@
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedJavaUnicodeString.h"
-#include "ScopedStringChars.h"
#include "unicode/translit.h"
static Transliterator* fromPeer(jlong peer) {
diff --git a/luni/src/main/native/libcore_io_OsConstants.cpp b/luni/src/main/native/libcore_io_OsConstants.cpp
index 56a159f..8f1f506 100644
--- a/luni/src/main/native/libcore_io_OsConstants.cpp
+++ b/luni/src/main/native/libcore_io_OsConstants.cpp
@@ -27,6 +27,7 @@
#include <poll.h>
#include <signal.h>
#include <stdlib.h>
+#include <sys/capability.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
@@ -55,6 +56,43 @@
#endif
initConstant(env, c, "AI_PASSIVE", AI_PASSIVE);
initConstant(env, c, "AI_V4MAPPED", AI_V4MAPPED);
+ initConstant(env, c, "CAP_AUDIT_CONTROL", CAP_AUDIT_CONTROL);
+ initConstant(env, c, "CAP_AUDIT_WRITE", CAP_AUDIT_WRITE);
+ initConstant(env, c, "CAP_CHOWN", CAP_CHOWN);
+ initConstant(env, c, "CAP_DAC_OVERRIDE", CAP_DAC_OVERRIDE);
+ initConstant(env, c, "CAP_DAC_READ_SEARCH", CAP_DAC_READ_SEARCH);
+ initConstant(env, c, "CAP_FOWNER", CAP_FOWNER);
+ initConstant(env, c, "CAP_FSETID", CAP_FSETID);
+ initConstant(env, c, "CAP_IPC_LOCK", CAP_IPC_LOCK);
+ initConstant(env, c, "CAP_IPC_OWNER", CAP_IPC_OWNER);
+ initConstant(env, c, "CAP_KILL", CAP_KILL);
+ initConstant(env, c, "CAP_LAST_CAP", CAP_LAST_CAP);
+ initConstant(env, c, "CAP_LEASE", CAP_LEASE);
+ initConstant(env, c, "CAP_LINUX_IMMUTABLE", CAP_LINUX_IMMUTABLE);
+ initConstant(env, c, "CAP_MAC_ADMIN", CAP_MAC_ADMIN);
+ initConstant(env, c, "CAP_MAC_OVERRIDE", CAP_MAC_OVERRIDE);
+ initConstant(env, c, "CAP_MKNOD", CAP_MKNOD);
+ initConstant(env, c, "CAP_NET_ADMIN", CAP_NET_ADMIN);
+ initConstant(env, c, "CAP_NET_BIND_SERVICE", CAP_NET_BIND_SERVICE);
+ initConstant(env, c, "CAP_NET_BROADCAST", CAP_NET_BROADCAST);
+ initConstant(env, c, "CAP_NET_RAW", CAP_NET_RAW);
+ initConstant(env, c, "CAP_SETFCAP", CAP_SETFCAP);
+ initConstant(env, c, "CAP_SETGID", CAP_SETGID);
+ initConstant(env, c, "CAP_SETPCAP", CAP_SETPCAP);
+ initConstant(env, c, "CAP_SETUID", CAP_SETUID);
+ initConstant(env, c, "CAP_SYS_ADMIN", CAP_SYS_ADMIN);
+ initConstant(env, c, "CAP_SYS_BOOT", CAP_SYS_BOOT);
+ initConstant(env, c, "CAP_SYS_CHROOT", CAP_SYS_CHROOT);
+ initConstant(env, c, "CAP_SYSLOG", CAP_SYSLOG);
+ initConstant(env, c, "CAP_SYS_MODULE", CAP_SYS_MODULE);
+ initConstant(env, c, "CAP_SYS_NICE", CAP_SYS_NICE);
+ initConstant(env, c, "CAP_SYS_PACCT", CAP_SYS_PACCT);
+ initConstant(env, c, "CAP_SYS_PTRACE", CAP_SYS_PTRACE);
+ initConstant(env, c, "CAP_SYS_RAWIO", CAP_SYS_RAWIO);
+ initConstant(env, c, "CAP_SYS_RESOURCE", CAP_SYS_RESOURCE);
+ initConstant(env, c, "CAP_SYS_TIME", CAP_SYS_TIME);
+ initConstant(env, c, "CAP_SYS_TTY_CONFIG", CAP_SYS_TTY_CONFIG);
+ initConstant(env, c, "CAP_WAKE_ALARM", CAP_WAKE_ALARM);
initConstant(env, c, "E2BIG", E2BIG);
initConstant(env, c, "EACCES", EACCES);
initConstant(env, c, "EADDRINUSE", EADDRINUSE);
@@ -203,6 +241,7 @@
#endif
initConstant(env, c, "IFF_UP", IFF_UP);
initConstant(env, c, "IPPROTO_ICMP", IPPROTO_ICMP);
+ initConstant(env, c, "IPPROTO_ICMPV6", IPPROTO_ICMPV6);
initConstant(env, c, "IPPROTO_IP", IPPROTO_IP);
initConstant(env, c, "IPPROTO_IPV6", IPPROTO_IPV6);
initConstant(env, c, "IPPROTO_RAW", IPPROTO_RAW);
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 1daa83d..7093a68 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 "ExecStrings.h"
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
@@ -36,7 +37,6 @@
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
-#include <netinet/in.h>
#include <poll.h>
#include <pwd.h>
#include <signal.h>
@@ -44,8 +44,8 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/socket.h>
-#include <sys/socket.h>
#include <sys/stat.h>
+#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
@@ -245,26 +245,28 @@
static_cast<jlong>(sb.st_blocks));
}
-static jobject makeStructStatFs(JNIEnv* env, const struct statfs& sb) {
+static jobject makeStructStatVfs(JNIEnv* env, const struct statvfs& sb) {
#if defined(__APPLE__)
// Mac OS has no f_namelen field in struct statfs.
jlong max_name_length = 255; // __DARWIN_MAXNAMLEN
#else
- // Until Mac OS 10.7, these were 32-bit fields.
- STATIC_ASSERT(sizeof(sb.f_bavail) == sizeof(jlong), statfs_not_64_bit);
- STATIC_ASSERT(sizeof(sb.f_bfree) == sizeof(jlong), statfs_not_64_bit);
- STATIC_ASSERT(sizeof(sb.f_blocks) == sizeof(jlong), statfs_not_64_bit);
-
- jlong max_name_length = static_cast<jlong>(sb.f_namelen);
+ jlong max_name_length = static_cast<jlong>(sb.f_namemax);
#endif
- static jmethodID ctor = env->GetMethodID(JniConstants::structStatFsClass, "<init>",
- "(JJJJJJJJ)V");
- return env->NewObject(JniConstants::structStatFsClass, ctor, static_cast<jlong>(sb.f_bsize),
- static_cast<jlong>(sb.f_blocks), static_cast<jlong>(sb.f_bfree),
- static_cast<jlong>(sb.f_bavail), static_cast<jlong>(sb.f_files),
- static_cast<jlong>(sb.f_ffree), max_name_length,
- static_cast<jlong>(sb.f_frsize));
+ static jmethodID ctor = env->GetMethodID(JniConstants::structStatVfsClass, "<init>",
+ "(JJJJJJJJJJJ)V");
+ return env->NewObject(JniConstants::structStatVfsClass, ctor,
+ static_cast<jlong>(sb.f_bsize),
+ static_cast<jlong>(sb.f_frsize),
+ static_cast<jlong>(sb.f_blocks),
+ static_cast<jlong>(sb.f_bfree),
+ static_cast<jlong>(sb.f_bavail),
+ static_cast<jlong>(sb.f_files),
+ static_cast<jlong>(sb.f_ffree),
+ static_cast<jlong>(sb.f_favail),
+ static_cast<jlong>(sb.f_fsid),
+ static_cast<jlong>(sb.f_flag),
+ max_name_length);
}
static jobject makeStructLinger(JNIEnv* env, const struct linger& l) {
@@ -357,11 +359,6 @@
public:
Passwd(JNIEnv* env) : mEnv(env), mResult(NULL) {
mBufferSize = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (mBufferSize == -1UL) {
- // We're probably on bionic, where 1KiB should be enough for anyone.
- // TODO: fix bionic to return 1024 like glibc.
- mBufferSize = 1024;
- }
mBuffer.reset(new char[mBufferSize]);
}
@@ -493,12 +490,10 @@
return;
}
- char** argv = convertStrings(env, javaArgv);
- char** envp = convertStrings(env, javaEnvp);
- execve(path.c_str(), argv, envp);
+ ExecStrings argv(env, javaArgv);
+ ExecStrings envp(env, javaEnvp);
+ execve(path.c_str(), argv.get(), envp.get());
- freeStrings(env, javaArgv, argv);
- freeStrings(env, javaEnvp, envp);
throwErrnoException(env, "execve");
}
@@ -508,10 +503,9 @@
return;
}
- char** argv = convertStrings(env, javaArgv);
- execv(path.c_str(), argv);
+ ExecStrings argv(env, javaArgv);
+ execv(path.c_str(), argv.get());
- freeStrings(env, javaArgv, argv);
throwErrnoException(env, "execv");
}
@@ -578,15 +572,15 @@
return makeStructStat(env, sb);
}
-static jobject Posix_fstatfs(JNIEnv* env, jobject, jobject javaFd) {
+static jobject Posix_fstatvfs(JNIEnv* env, jobject, jobject javaFd) {
int fd = jniGetFDFromFileDescriptor(env, javaFd);
- struct statfs sb;
- int rc = TEMP_FAILURE_RETRY(fstatfs(fd, &sb));
+ struct statvfs sb;
+ int rc = TEMP_FAILURE_RETRY(fstatvfs(fd, &sb));
if (rc == -1) {
- throwErrnoException(env, "fstatfs");
+ throwErrnoException(env, "fstatvfs");
return NULL;
}
- return makeStructStatFs(env, sb);
+ return makeStructStatVfs(env, sb);
}
static void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) {
@@ -804,6 +798,11 @@
return makeStructUcred(env, u);
}
+static jint Posix_gettid(JNIEnv*, jobject) {
+ // Neither bionic nor glibc exposes gettid(2).
+ return syscall(__NR_gettid);
+}
+
static jint Posix_getuid(JNIEnv*, jobject) {
return getuid();
}
@@ -1260,18 +1259,18 @@
return doStat(env, javaPath, false);
}
-static jobject Posix_statfs(JNIEnv* env, jobject, jstring javaPath) {
+static jobject Posix_statvfs(JNIEnv* env, jobject, jstring javaPath) {
ScopedUtfChars path(env, javaPath);
if (path.c_str() == NULL) {
return NULL;
}
- struct statfs sb;
- int rc = TEMP_FAILURE_RETRY(statfs(path.c_str(), &sb));
+ struct statvfs sb;
+ int rc = TEMP_FAILURE_RETRY(statvfs(path.c_str(), &sb));
if (rc == -1) {
- throwErrnoException(env, "statfs");
+ throwErrnoException(env, "statvfs");
return NULL;
}
- return makeStructStatFs(env, sb);
+ return makeStructStatVfs(env, sb);
}
static jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) {
@@ -1384,7 +1383,7 @@
NATIVE_METHOD(Posix, fcntlFlock, "(Ljava/io/FileDescriptor;ILlibcore/io/StructFlock;)I"),
NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"),
NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStat;"),
- NATIVE_METHOD(Posix, fstatfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatFs;"),
+ NATIVE_METHOD(Posix, fstatvfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatVfs;"),
NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"),
NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"),
NATIVE_METHOD(Posix, gai_strerror, "(I)Ljava/lang/String;"),
@@ -1406,6 +1405,7 @@
NATIVE_METHOD(Posix, getsockoptLinger, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructLinger;"),
NATIVE_METHOD(Posix, getsockoptTimeval, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructTimeval;"),
NATIVE_METHOD(Posix, getsockoptUcred, "(Ljava/io/FileDescriptor;II)Llibcore/io/StructUcred;"),
+ NATIVE_METHOD(Posix, gettid, "()I"),
NATIVE_METHOD(Posix, getuid, "()I"),
NATIVE_METHOD(Posix, if_indextoname, "(I)Ljava/lang/String;"),
NATIVE_METHOD(Posix, inet_pton, "(ILjava/lang/String;)Ljava/net/InetAddress;"),
@@ -1453,7 +1453,7 @@
NATIVE_METHOD(Posix, socket, "(III)Ljava/io/FileDescriptor;"),
NATIVE_METHOD(Posix, socketpair, "(IIILjava/io/FileDescriptor;Ljava/io/FileDescriptor;)V"),
NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Llibcore/io/StructStat;"),
- NATIVE_METHOD(Posix, statfs, "(Ljava/lang/String;)Llibcore/io/StructStatFs;"),
+ NATIVE_METHOD(Posix, statvfs, "(Ljava/lang/String;)Llibcore/io/StructStatVfs;"),
NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"),
NATIVE_METHOD(Posix, strsignal, "(I)Ljava/lang/String;"),
NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"),
diff --git a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 9b4bb4d..6ba055a 100644
--- a/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/luni/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -332,6 +332,7 @@
memcpy(newBucket, existingBucket, size * sizeof(InternedString*));
newBucket[size] = entry;
newBucket[size + 1] = NULL;
+ delete[] existingBucket;
return newBucket;
}
@@ -385,6 +386,7 @@
// Expand the bucket.
bucket = expandInternedStringBucket(bucket, internedString);
if (bucket == NULL) {
+ delete internedString;
jniThrowOutOfMemoryError(env, NULL);
return NULL;
}
@@ -400,6 +402,7 @@
// Create a new bucket with one entry.
bucket = newInternedStringBucket(internedString);
if (bucket == NULL) {
+ delete internedString;
jniThrowOutOfMemoryError(env, NULL);
return NULL;
}
diff --git a/luni/src/main/native/sub.mk b/luni/src/main/native/sub.mk
index 7ea5033..e576d1a 100644
--- a/luni/src/main/native/sub.mk
+++ b/luni/src/main/native/sub.mk
@@ -5,8 +5,8 @@
LOCAL_SRC_FILES := \
AsynchronousSocketCloseMonitor.cpp \
+ ExecStrings.cpp \
IcuUtilities.cpp \
- JniConstants.cpp \
JniException.cpp \
NetworkUtilities.cpp \
Register.cpp \
@@ -15,6 +15,8 @@
java_io_File.cpp \
java_io_ObjectStreamClass.cpp \
java_lang_Character.cpp \
+ java_lang_Double.cpp \
+ java_lang_Float.cpp \
java_lang_Math.cpp \
java_lang_ProcessManager.cpp \
java_lang_RealToString.cpp \
@@ -32,6 +34,7 @@
java_util_zip_Deflater.cpp \
java_util_zip_Inflater.cpp \
libcore_icu_AlphabeticIndex.cpp \
+ libcore_icu_DateIntervalFormat.cpp \
libcore_icu_ICU.cpp \
libcore_icu_NativeBreakIterator.cpp \
libcore_icu_NativeCollation.cpp \
@@ -48,11 +51,9 @@
libcore_io_Posix.cpp \
libcore_net_RawSocket.cpp \
org_apache_harmony_xml_ExpatParser.cpp \
- org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp \
readlink.cpp \
realpath.cpp \
sun_misc_Unsafe.cpp \
- toStringArray.cpp \
valueOf.cpp
LOCAL_C_INCLUDES += \
diff --git a/luni/src/main/native/toStringArray.cpp b/luni/src/main/native/toStringArray.cpp
deleted file mode 100644
index 9640d22..0000000
--- a/luni/src/main/native/toStringArray.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.
- */
-
-#include "JniConstants.h"
-#include "toStringArray.h"
-
-#include <string>
-#include <vector>
-
-struct VectorCounter {
- const std::vector<std::string>& strings;
- VectorCounter(const std::vector<std::string>& strings) : strings(strings) {}
- size_t operator()() {
- return strings.size();
- }
-};
-struct VectorGetter {
- const std::vector<std::string>& strings;
- VectorGetter(const std::vector<std::string>& strings) : strings(strings) {}
- const char* operator()(size_t i) {
- return strings[i].c_str();
- }
-};
-
-jobjectArray toStringArray(JNIEnv* env, const std::vector<std::string>& strings) {
- VectorCounter counter(strings);
- VectorGetter getter(strings);
- return toStringArray<VectorCounter, VectorGetter>(env, &counter, &getter);
-}
-
-struct ArrayCounter {
- const char* const* strings;
- ArrayCounter(const char* const* strings) : strings(strings) {}
- size_t operator()() {
- size_t count = 0;
- while (strings[count] != NULL) {
- ++count;
- }
- return count;
- }
-};
-
-struct ArrayGetter {
- const char* const* strings;
- ArrayGetter(const char* const* strings) : strings(strings) {}
- const char* operator()(size_t i) {
- return strings[i];
- }
-};
-
-jobjectArray toStringArray(JNIEnv* env, const char* const* strings) {
- ArrayCounter counter(strings);
- ArrayGetter getter(strings);
- return toStringArray(env, &counter, &getter);
-}
-
-/** Converts a Java String[] to a 0-terminated char**. */
-char** convertStrings(JNIEnv* env, jobjectArray javaArray) {
- if (javaArray == NULL) {
- return NULL;
- }
-
- jsize length = env->GetArrayLength(javaArray);
- char** array = new char*[length + 1];
- array[length] = 0;
- for (jsize i = 0; i < length; ++i) {
- ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i)));
- // We need to pass these strings to const-unfriendly code.
- char* entry = const_cast<char*>(env->GetStringUTFChars(javaEntry.get(), NULL));
- array[i] = entry;
- }
-
- return array;
-}
-
-/** Frees a char** which was converted from a Java String[]. */
-void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array) {
- if (javaArray == NULL) {
- return;
- }
-
- jsize length = env->GetArrayLength(javaArray);
- for (jsize i = 0; i < length; ++i) {
- ScopedLocalRef<jstring> javaEntry(env, reinterpret_cast<jstring>(env->GetObjectArrayElement(javaArray, i)));
- env->ReleaseStringUTFChars(javaEntry.get(), array[i]);
- }
-
- delete[] array;
-}
diff --git a/luni/src/main/native/toStringArray.h b/luni/src/main/native/toStringArray.h
deleted file mode 100644
index c65b8ad..0000000
--- a/luni/src/main/native/toStringArray.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.
- */
-
-#include "jni.h"
-#include "ScopedLocalRef.h"
-
-#include <string>
-#include <vector>
-
-template <typename Counter, typename Getter>
-jobjectArray toStringArray(JNIEnv* env, Counter* counter, Getter* getter) {
- size_t count = (*counter)();
- jobjectArray result = env->NewObjectArray(count, JniConstants::stringClass, NULL);
- if (result == NULL) {
- return NULL;
- }
- for (size_t i = 0; i < count; ++i) {
- ScopedLocalRef<jstring> s(env, env->NewStringUTF((*getter)(i)));
- if (env->ExceptionCheck()) {
- return NULL;
- }
- env->SetObjectArrayElement(result, i, s.get());
- if (env->ExceptionCheck()) {
- return NULL;
- }
- }
- return result;
-}
-
-template <typename Counter, typename Getter>
-jobjectArray toStringArray16(JNIEnv* env, Counter* counter, Getter* getter) {
- size_t count = (*counter)();
- jobjectArray result = env->NewObjectArray(count, JniConstants::stringClass, NULL);
- if (result == NULL) {
- return NULL;
- }
- for (size_t i = 0; i < count; ++i) {
- int32_t charCount;
- const jchar* chars = (*getter)(&charCount);
- ScopedLocalRef<jstring> s(env, env->NewString(chars, charCount));
- if (env->ExceptionCheck()) {
- return NULL;
- }
- env->SetObjectArrayElement(result, i, s.get());
- if (env->ExceptionCheck()) {
- return NULL;
- }
- }
- return result;
-}
-
-jobjectArray toStringArray(JNIEnv* env, const std::vector<std::string>& strings);
-jobjectArray toStringArray(JNIEnv* env, const char* const* strings);
-
-char** convertStrings(JNIEnv* env, jobjectArray javaArray);
-void freeStrings(JNIEnv* env, jobjectArray javaArray, char** array);
diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
new file mode 100644
index 0000000..8de3407
--- /dev/null
+++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.icu;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+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;
+
+ public void test_formatDateInterval() throws Exception {
+ Date date = new Date(109, 0, 19, 3, 30, 15);
+ long fixedTime = date.getTime();
+
+ int currentYear = Calendar.getInstance().get(Calendar.YEAR);
+ Date dateWithCurrentYear = new Date(currentYear - 1900, 0, 19, 3, 30, 15);
+ long timeWithCurrentYear = dateWithCurrentYear.getTime();
+
+ 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("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("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));
+ assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME));
+ assertEquals("12:00 PM", formatDateRange(en_US, tz, fixedTime + noonDuration, fixedTime + noonDuration, FORMAT_12HOUR | FORMAT_SHOW_TIME /*| FORMAT_CAP_NOON*/));
+ 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("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("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("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("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));
+
+ // 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 – 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("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));
+
+ // 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. 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. 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));
+
+ // 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 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 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));
+
+ // 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 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 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));
+ }
+
+ public void test8862241() throws Exception {
+ // Test the post-2038 future (http://b/8862241).
+ 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));
+ }
+
+ public void test10089890() throws Exception {
+ // Test that we actually take the time zone into account.
+ // 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"));
+ // 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"));
+ }
+}
diff --git a/luni/src/test/java/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/icu/ICUTest.java
index 9d9892c..b3d16f9 100644
--- a/luni/src/test/java/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/icu/ICUTest.java
@@ -16,58 +16,111 @@
package libcore.icu;
+import java.util.Arrays;
import java.util.Locale;
public class ICUTest extends junit.framework.TestCase {
- public void test_getISOLanguages() throws Exception {
- // Check that corrupting our array doesn't affect other callers.
- assertNotNull(ICU.getISOLanguages()[0]);
- ICU.getISOLanguages()[0] = null;
- assertNotNull(ICU.getISOLanguages()[0]);
+ public void test_getISOLanguages() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(ICU.getISOLanguages()[0]);
+ ICU.getISOLanguages()[0] = null;
+ assertNotNull(ICU.getISOLanguages()[0]);
+ }
+
+ public void test_getISOCountries() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(ICU.getISOCountries()[0]);
+ ICU.getISOCountries()[0] = null;
+ assertNotNull(ICU.getISOCountries()[0]);
+ }
+
+ public void test_getAvailableLocales() throws Exception {
+ // Check that corrupting our array doesn't affect other callers.
+ assertNotNull(ICU.getAvailableLocales()[0]);
+ ICU.getAvailableLocales()[0] = null;
+ assertNotNull(ICU.getAvailableLocales()[0]);
+ }
+
+ public void test_getBestDateTimePattern() throws Exception {
+ assertEquals("d MMMM", ICU.getBestDateTimePattern("MMMMd", "ca_ES"));
+ assertEquals("d 'de' MMMM", ICU.getBestDateTimePattern("MMMMd", "es_ES"));
+ assertEquals("d. MMMM", ICU.getBestDateTimePattern("MMMMd", "de_CH"));
+ assertEquals("MMMM d", ICU.getBestDateTimePattern("MMMMd", "en_US"));
+ assertEquals("d LLLL", ICU.getBestDateTimePattern("MMMMd", "fa_IR"));
+ assertEquals("M月d日", ICU.getBestDateTimePattern("MMMMd", "ja_JP"));
+ }
+
+ public void test_localeFromString() throws Exception {
+ // localeFromString is pretty lenient. Some of these can't be round-tripped
+ // through Locale.toString.
+ assertEquals(Locale.ENGLISH, ICU.localeFromString("en"));
+ assertEquals(Locale.ENGLISH, ICU.localeFromString("en_"));
+ assertEquals(Locale.ENGLISH, ICU.localeFromString("en__"));
+ assertEquals(Locale.US, ICU.localeFromString("en_US"));
+ assertEquals(Locale.US, ICU.localeFromString("en_US_"));
+ assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US"));
+ assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US_"));
+ assertEquals(new Locale("", "", "POSIX"), ICU.localeFromString("__POSIX"));
+ assertEquals(new Locale("aa", "BB", "CC"), ICU.localeFromString("aa_BB_CC"));
+ }
+
+ public void test_getScript_addLikelySubtags() throws Exception {
+ assertEquals("Latn", ICU.getScript(ICU.addLikelySubtags("en_US")));
+ assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he")));
+ assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he_IL")));
+ assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw")));
+ assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw_IL")));
+ }
+
+ private String best(Locale l, String skeleton) {
+ return ICU.getBestDateTimePattern(skeleton, l.toString());
+ }
+
+ public void test_getDateFormatOrder() throws Exception {
+ // lv and fa use differing orders depending on whether you're using numeric or textual months.
+ Locale lv = new Locale("lv");
+ assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "yyyy-M-dd"))));
+ assertEquals("[y, d, M]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "yyyy-MMM-dd"))));
+ assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(lv, "MMM-dd"))));
+ Locale fa = new Locale("fa");
+ assertEquals("[y, M, d]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "yyyy-M-dd"))));
+ assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "yyyy-MMM-dd"))));
+ assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(fa, "MMM-dd"))));
+
+ // English differs on each side of the Atlantic.
+ Locale en_US = Locale.US;
+ assertEquals("[M, d, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "yyyy-M-dd"))));
+ assertEquals("[M, d, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "yyyy-MMM-dd"))));
+ assertEquals("[M, d, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(en_US, "MMM-dd"))));
+ Locale en_GB = Locale.UK;
+ assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "yyyy-M-dd"))));
+ assertEquals("[d, M, y]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "yyyy-MMM-dd"))));
+ assertEquals("[d, M, \u0000]", Arrays.toString(ICU.getDateFormatOrder(best(en_GB, "MMM-dd"))));
+
+ assertEquals("[y, M, d]", Arrays.toString(ICU.getDateFormatOrder("yyyy - 'why' '' 'ddd' MMM-dd")));
+
+ try {
+ ICU.getDateFormatOrder("the quick brown fox jumped over the lazy dog");
+ fail();
+ } catch (IllegalArgumentException expected) {
}
- public void test_getISOCountries() throws Exception {
- // Check that corrupting our array doesn't affect other callers.
- assertNotNull(ICU.getISOCountries()[0]);
- ICU.getISOCountries()[0] = null;
- assertNotNull(ICU.getISOCountries()[0]);
+ try {
+ ICU.getDateFormatOrder("'");
+ fail();
+ } catch (IllegalArgumentException expected) {
}
- public void test_getAvailableLocales() throws Exception {
- // Check that corrupting our array doesn't affect other callers.
- assertNotNull(ICU.getAvailableLocales()[0]);
- ICU.getAvailableLocales()[0] = null;
- assertNotNull(ICU.getAvailableLocales()[0]);
+ try {
+ ICU.getDateFormatOrder("yyyy'");
+ fail();
+ } catch (IllegalArgumentException expected) {
}
- public void test_getBestDateTimePattern() throws Exception {
- assertEquals("d MMMM", ICU.getBestDateTimePattern("MMMMd", "ca_ES"));
- assertEquals("d 'de' MMMM", ICU.getBestDateTimePattern("MMMMd", "es_ES"));
- assertEquals("d. MMMM", ICU.getBestDateTimePattern("MMMMd", "de_CH"));
- assertEquals("MMMM d", ICU.getBestDateTimePattern("MMMMd", "en_US"));
- assertEquals("d LLLL", ICU.getBestDateTimePattern("MMMMd", "fa_IR"));
- assertEquals("M月d日", ICU.getBestDateTimePattern("MMMMd", "ja_JP"));
+ try {
+ ICU.getDateFormatOrder("yyyy'MMM");
+ fail();
+ } catch (IllegalArgumentException expected) {
}
-
- public void test_localeFromString() throws Exception {
- // localeFromString is pretty lenient. Some of these can't be round-tripped
- // through Locale.toString.
- assertEquals(Locale.ENGLISH, ICU.localeFromString("en"));
- assertEquals(Locale.ENGLISH, ICU.localeFromString("en_"));
- assertEquals(Locale.ENGLISH, ICU.localeFromString("en__"));
- assertEquals(Locale.US, ICU.localeFromString("en_US"));
- assertEquals(Locale.US, ICU.localeFromString("en_US_"));
- assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US"));
- assertEquals(new Locale("", "US", ""), ICU.localeFromString("_US_"));
- assertEquals(new Locale("", "", "POSIX"), ICU.localeFromString("__POSIX"));
- assertEquals(new Locale("aa", "BB", "CC"), ICU.localeFromString("aa_BB_CC"));
- }
-
- public void test_getScript_addLikelySubtags() throws Exception {
- assertEquals("Latn", ICU.getScript(ICU.addLikelySubtags("en_US")));
- assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he")));
- assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("he_IL")));
- assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw")));
- assertEquals("Hebr", ICU.getScript(ICU.addLikelySubtags("iw_IL")));
- }
+ }
}
diff --git a/luni/src/test/java/libcore/icu/TransliteratorTest.java b/luni/src/test/java/libcore/icu/TransliteratorTest.java
index e4f7981..9ced2de 100644
--- a/luni/src/test/java/libcore/icu/TransliteratorTest.java
+++ b/luni/src/test/java/libcore/icu/TransliteratorTest.java
@@ -90,7 +90,7 @@
t = new Transliterator("Han-Latin/Names");
assertEquals("shěn", t.transliterate("\u6c88"));
assertEquals("shěn", t.transliterate("\u700b"));
- assertEquals("jǐa", t.transliterate("\u8d3e"));
+ assertEquals("jiǎ", t.transliterate("\u8d3e"));
t = new Transliterator("Han-Latin/Names; Latin-Ascii; Any-Upper");
assertEquals("SHEN", t.transliterate("\u6c88"));
diff --git a/luni/src/test/java/libcore/io/DiskLruCacheTest.java b/luni/src/test/java/libcore/io/DiskLruCacheTest.java
deleted file mode 100644
index 7a5bfa5..0000000
--- a/luni/src/test/java/libcore/io/DiskLruCacheTest.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * 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 libcore.io;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import junit.framework.TestCase;
-import static libcore.io.DiskLruCache.JOURNAL_FILE;
-import static libcore.io.DiskLruCache.MAGIC;
-import static libcore.io.DiskLruCache.VERSION_1;
-import tests.io.MockOs;
-
-public final class DiskLruCacheTest extends TestCase {
- private final int appVersion = 100;
- private String javaTmpDir;
- private File cacheDir;
- private File journalFile;
- private DiskLruCache cache;
- private final MockOs mockOs = new MockOs();
-
- @Override public void setUp() throws Exception {
- super.setUp();
- javaTmpDir = System.getProperty("java.io.tmpdir");
- cacheDir = new File(javaTmpDir, "DiskLruCacheTest");
- cacheDir.mkdir();
- journalFile = new File(cacheDir, JOURNAL_FILE);
- for (File file : cacheDir.listFiles()) {
- file.delete();
- }
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- mockOs.install();
- }
-
- @Override protected void tearDown() throws Exception {
- mockOs.uninstall();
- cache.close();
- super.tearDown();
- }
-
- public void testEmptyCache() throws Exception {
- cache.close();
- assertJournalEquals();
- }
-
- public void testWriteAndReadEntry() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(0, "ABC");
- creator.set(1, "DE");
- assertNull(creator.getString(0));
- assertNull(creator.newInputStream(0));
- assertNull(creator.getString(1));
- assertNull(creator.newInputStream(1));
- creator.commit();
-
- DiskLruCache.Snapshot snapshot = cache.get("k1");
- assertEquals("ABC", snapshot.getString(0));
- assertEquals("DE", snapshot.getString(1));
- }
-
- public void testReadAndWriteEntryAcrossCacheOpenAndClose() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(0, "A");
- creator.set(1, "B");
- creator.commit();
- cache.close();
-
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- DiskLruCache.Snapshot snapshot = cache.get("k1");
- assertEquals("A", snapshot.getString(0));
- assertEquals("B", snapshot.getString(1));
- snapshot.close();
- }
-
- public void testJournalWithEditAndPublish() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- assertJournalEquals("DIRTY k1"); // DIRTY must always be flushed
- creator.set(0, "AB");
- creator.set(1, "C");
- creator.commit();
- cache.close();
- assertJournalEquals("DIRTY k1", "CLEAN k1 2 1");
- }
-
- public void testRevertedNewFileIsRemoveInJournal() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- assertJournalEquals("DIRTY k1"); // DIRTY must always be flushed
- creator.set(0, "AB");
- creator.set(1, "C");
- creator.abort();
- cache.close();
- assertJournalEquals("DIRTY k1", "REMOVE k1");
- }
-
- public void testUnterminatedEditIsRevertedOnClose() throws Exception {
- cache.edit("k1");
- cache.close();
- assertJournalEquals("DIRTY k1", "REMOVE k1");
- }
-
- public void testJournalDoesNotIncludeReadOfYetUnpublishedValue() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- assertNull(cache.get("k1"));
- creator.set(0, "A");
- creator.set(1, "BC");
- creator.commit();
- cache.close();
- assertJournalEquals("DIRTY k1", "CLEAN k1 1 2");
- }
-
- public void testJournalWithEditAndPublishAndRead() throws Exception {
- DiskLruCache.Editor k1Creator = cache.edit("k1");
- k1Creator.set(0, "AB");
- k1Creator.set(1, "C");
- k1Creator.commit();
- DiskLruCache.Editor k2Creator = cache.edit("k2");
- k2Creator.set(0, "DEF");
- k2Creator.set(1, "G");
- k2Creator.commit();
- DiskLruCache.Snapshot k1Snapshot = cache.get("k1");
- k1Snapshot.close();
- cache.close();
- assertJournalEquals("DIRTY k1", "CLEAN k1 2 1",
- "DIRTY k2", "CLEAN k2 3 1",
- "READ k1");
- }
-
- public void testCannotOperateOnEditAfterPublish() throws Exception {
- DiskLruCache.Editor editor = cache.edit("k1");
- editor.set(0, "A");
- editor.set(1, "B");
- editor.commit();
- assertInoperable(editor);
- }
-
- public void testCannotOperateOnEditAfterRevert() throws Exception {
- DiskLruCache.Editor editor = cache.edit("k1");
- editor.set(0, "A");
- editor.set(1, "B");
- editor.abort();
- assertInoperable(editor);
- }
-
- public void testExplicitRemoveAppliedToDiskImmediately() throws Exception {
- DiskLruCache.Editor editor = cache.edit("k1");
- editor.set(0, "ABC");
- editor.set(1, "B");
- editor.commit();
- File k1 = getCleanFile("k1", 0);
- assertEquals("ABC", readFile(k1));
- cache.remove("k1");
- assertFalse(k1.exists());
- }
-
- /**
- * Each read sees a snapshot of the file at the time read was called.
- * This means that two reads of the same key can see different data.
- */
- public void testReadAndWriteOverlapsMaintainConsistency() throws Exception {
- DiskLruCache.Editor v1Creator = cache.edit("k1");
- v1Creator.set(0, "AAaa");
- v1Creator.set(1, "BBbb");
- v1Creator.commit();
-
- DiskLruCache.Snapshot snapshot1 = cache.get("k1");
- InputStream inV1 = snapshot1.getInputStream(0);
- assertEquals('A', inV1.read());
- assertEquals('A', inV1.read());
-
- DiskLruCache.Editor v1Updater = cache.edit("k1");
- v1Updater.set(0, "CCcc");
- v1Updater.set(1, "DDdd");
- v1Updater.commit();
-
- DiskLruCache.Snapshot snapshot2 = cache.get("k1");
- assertEquals("CCcc", snapshot2.getString(0));
- assertEquals("DDdd", snapshot2.getString(1));
- snapshot2.close();
-
- assertEquals('a', inV1.read());
- assertEquals('a', inV1.read());
- assertEquals("BBbb", snapshot1.getString(1));
- snapshot1.close();
- }
-
- public void testOpenWithDirtyKeyDeletesAllFilesForThatKey() throws Exception {
- cache.close();
- File cleanFile0 = getCleanFile("k1", 0);
- File cleanFile1 = getCleanFile("k1", 1);
- File dirtyFile0 = getDirtyFile("k1", 0);
- File dirtyFile1 = getDirtyFile("k1", 1);
- writeFile(cleanFile0, "A");
- writeFile(cleanFile1, "B");
- writeFile(dirtyFile0, "C");
- writeFile(dirtyFile1, "D");
- createJournal("CLEAN k1 1 1", "DIRTY k1");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertFalse(cleanFile0.exists());
- assertFalse(cleanFile1.exists());
- assertFalse(dirtyFile0.exists());
- assertFalse(dirtyFile1.exists());
- assertNull(cache.get("k1"));
- }
-
- public void testOpenWithInvalidVersionClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournalWithHeader(MAGIC, "0", "100", "2", "");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- }
-
- public void testOpenWithInvalidAppVersionClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournalWithHeader(MAGIC, "1", "101", "2", "");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- }
-
- public void testOpenWithInvalidValueCountClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournalWithHeader(MAGIC, "1", "100", "1", "");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- }
-
- public void testOpenWithInvalidBlankLineClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournalWithHeader(MAGIC, "1", "100", "2", "x");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- }
-
- public void testOpenWithInvalidJournalLineClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournal("CLEAN k1 1 1", "BOGUS");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- assertNull(cache.get("k1"));
- }
-
- public void testOpenWithInvalidFileSizeClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournal("CLEAN k1 0000x001 1");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- assertNull(cache.get("k1"));
- }
-
- public void testOpenWithTruncatedLineDiscardsThatLine() throws Exception {
- cache.close();
- writeFile(getCleanFile("k1", 0), "A");
- writeFile(getCleanFile("k1", 1), "B");
- Writer writer = new FileWriter(journalFile);
- writer.write(MAGIC + "\n" + VERSION_1 + "\n100\n2\n\nCLEAN k1 1 1"); // no trailing newline
- writer.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertNull(cache.get("k1"));
- }
-
- public void testOpenWithTooManyFileSizesClearsDirectory() throws Exception {
- cache.close();
- generateSomeGarbageFiles();
- createJournal("CLEAN k1 1 1 1");
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- assertGarbageFilesAllDeleted();
- assertNull(cache.get("k1"));
- }
-
- public void testKeyWithSpaceNotPermitted() throws Exception {
- try {
- cache.edit("my key");
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testKeyWithNewlineNotPermitted() throws Exception {
- try {
- cache.edit("my\nkey");
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testKeyWithCarriageReturnNotPermitted() throws Exception {
- try {
- cache.edit("my\rkey");
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testNullKeyThrows() throws Exception {
- try {
- cache.edit(null);
- fail();
- } catch (NullPointerException expected) {
- }
- }
-
- public void testCreateNewEntryWithTooFewValuesFails() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(1, "A");
- try {
- creator.commit();
- fail();
- } catch (IllegalStateException expected) {
- }
-
- assertFalse(getCleanFile("k1", 0).exists());
- assertFalse(getCleanFile("k1", 1).exists());
- assertFalse(getDirtyFile("k1", 0).exists());
- assertFalse(getDirtyFile("k1", 1).exists());
- assertNull(cache.get("k1"));
-
- DiskLruCache.Editor creator2 = cache.edit("k1");
- creator2.set(0, "B");
- creator2.set(1, "C");
- creator2.commit();
- }
-
- public void testCreateNewEntryWithMissingFileAborts() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(0, "A");
- creator.set(1, "A");
- assertTrue(getDirtyFile("k1", 0).exists());
- assertTrue(getDirtyFile("k1", 1).exists());
- assertTrue(getDirtyFile("k1", 0).delete());
- assertFalse(getDirtyFile("k1", 0).exists());
- creator.commit(); // silently abort if file does not exist due to I/O issue
-
- assertFalse(getCleanFile("k1", 0).exists());
- assertFalse(getCleanFile("k1", 1).exists());
- assertFalse(getDirtyFile("k1", 0).exists());
- assertFalse(getDirtyFile("k1", 1).exists());
- assertNull(cache.get("k1"));
-
- DiskLruCache.Editor creator2 = cache.edit("k1");
- creator2.set(0, "B");
- creator2.set(1, "C");
- creator2.commit();
- }
-
- public void testRevertWithTooFewValues() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(1, "A");
- creator.abort();
- assertFalse(getCleanFile("k1", 0).exists());
- assertFalse(getCleanFile("k1", 1).exists());
- assertFalse(getDirtyFile("k1", 0).exists());
- assertFalse(getDirtyFile("k1", 1).exists());
- assertNull(cache.get("k1"));
- }
-
- public void testUpdateExistingEntryWithTooFewValuesReusesPreviousValues() throws Exception {
- DiskLruCache.Editor creator = cache.edit("k1");
- creator.set(0, "A");
- creator.set(1, "B");
- creator.commit();
-
- DiskLruCache.Editor updater = cache.edit("k1");
- updater.set(0, "C");
- updater.commit();
-
- DiskLruCache.Snapshot snapshot = cache.get("k1");
- assertEquals("C", snapshot.getString(0));
- assertEquals("B", snapshot.getString(1));
- snapshot.close();
- }
-
- public void testEvictOnInsert() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
- set("A", "a", "aaa"); // size 4
- set("B", "bb", "bbbb"); // size 6
- assertEquals(10, cache.size());
-
- // cause the size to grow to 12 should evict 'A'
- set("C", "c", "c");
- cache.flush();
- assertEquals(8, cache.size());
- assertAbsent("A");
- assertValue("B", "bb", "bbbb");
- assertValue("C", "c", "c");
-
- // causing the size to grow to 10 should evict nothing
- set("D", "d", "d");
- cache.flush();
- assertEquals(10, cache.size());
- assertAbsent("A");
- assertValue("B", "bb", "bbbb");
- assertValue("C", "c", "c");
- assertValue("D", "d", "d");
-
- // causing the size to grow to 18 should evict 'B' and 'C'
- set("E", "eeee", "eeee");
- cache.flush();
- assertEquals(10, cache.size());
- assertAbsent("A");
- assertAbsent("B");
- assertAbsent("C");
- assertValue("D", "d", "d");
- assertValue("E", "eeee", "eeee");
- }
-
- public void testEvictOnUpdate() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
- set("A", "a", "aa"); // size 3
- set("B", "b", "bb"); // size 3
- set("C", "c", "cc"); // size 3
- assertEquals(9, cache.size());
-
- // causing the size to grow to 11 should evict 'A'
- set("B", "b", "bbbb");
- cache.flush();
- assertEquals(8, cache.size());
- assertAbsent("A");
- assertValue("B", "b", "bbbb");
- assertValue("C", "c", "cc");
- }
-
- public void testEvictionHonorsLruFromCurrentSession() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
- set("A", "a", "a");
- set("B", "b", "b");
- set("C", "c", "c");
- set("D", "d", "d");
- set("E", "e", "e");
- cache.get("B").close(); // 'B' is now least recently used
-
- // causing the size to grow to 12 should evict 'A'
- set("F", "f", "f");
- // causing the size to grow to 12 should evict 'C'
- set("G", "g", "g");
- cache.flush();
- assertEquals(10, cache.size());
- assertAbsent("A");
- assertValue("B", "b", "b");
- assertAbsent("C");
- assertValue("D", "d", "d");
- assertValue("E", "e", "e");
- assertValue("F", "f", "f");
- }
-
- public void testEvictionHonorsLruFromPreviousSession() throws Exception {
- set("A", "a", "a");
- set("B", "b", "b");
- set("C", "c", "c");
- set("D", "d", "d");
- set("E", "e", "e");
- set("F", "f", "f");
- cache.get("B").close(); // 'B' is now least recently used
- assertEquals(12, cache.size());
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
-
- set("G", "g", "g");
- cache.flush();
- assertEquals(10, cache.size());
- assertAbsent("A");
- assertValue("B", "b", "b");
- assertAbsent("C");
- assertValue("D", "d", "d");
- assertValue("E", "e", "e");
- assertValue("F", "f", "f");
- assertValue("G", "g", "g");
- }
-
- public void testCacheSingleEntryOfSizeGreaterThanMaxSize() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
- set("A", "aaaaa", "aaaaaa"); // size=11
- cache.flush();
- assertAbsent("A");
- }
-
- public void testCacheSingleValueOfSizeGreaterThanMaxSize() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
- set("A", "aaaaaaaaaaa", "a"); // size=12
- cache.flush();
- assertAbsent("A");
- }
-
- public void testConstructorDoesNotAllowZeroCacheSize() throws Exception {
- try {
- DiskLruCache.open(cacheDir, appVersion, 2, 0);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testConstructorDoesNotAllowZeroValuesPerEntry() throws Exception {
- try {
- DiskLruCache.open(cacheDir, appVersion, 0, 10);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- }
-
- public void testRemoveAbsentElement() throws Exception {
- cache.remove("A");
- }
-
- public void testReadingTheSameStreamMultipleTimes() throws Exception {
- set("A", "a", "b");
- DiskLruCache.Snapshot snapshot = cache.get("A");
- assertSame(snapshot.getInputStream(0), snapshot.getInputStream(0));
- snapshot.close();
- }
-
- public void testRebuildJournalOnRepeatedReads() throws Exception {
- set("A", "a", "a");
- set("B", "b", "b");
- long lastJournalLength = 0;
- while (true) {
- long journalLength = journalFile.length();
- assertValue("A", "a", "a");
- assertValue("B", "b", "b");
- if (journalLength < lastJournalLength) {
- System.out.printf("Journal compacted from %s bytes to %s bytes\n",
- lastJournalLength, journalLength);
- break; // test passed!
- }
- lastJournalLength = journalLength;
- }
- }
-
- public void testRebuildJournalOnRepeatedEdits() throws Exception {
- long lastJournalLength = 0;
- while (true) {
- long journalLength = journalFile.length();
- set("A", "a", "a");
- set("B", "b", "b");
- if (journalLength < lastJournalLength) {
- System.out.printf("Journal compacted from %s bytes to %s bytes\n",
- lastJournalLength, journalLength);
- break;
- }
- lastJournalLength = journalLength;
- }
-
- // sanity check that a rebuilt journal behaves normally
- assertValue("A", "a", "a");
- assertValue("B", "b", "b");
- }
-
- /** @see <a href="https://github.com/JakeWharton/DiskLruCache/issues/28">Issue #28</a> */
- public void testRebuildJournalOnRepeatedReadsWithOpenAndClose() throws Exception {
- set("a", "a", "a");
- set("b", "b", "b");
- long lastJournalLength = 0;
- while (true) {
- long journalLength = journalFile.length();
- assertValue("a", "a", "a");
- assertValue("b", "b", "b");
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- if (journalLength < lastJournalLength) {
- System.out.printf("Journal compacted from %s bytes to %s bytes\n",
- lastJournalLength, journalLength);
- break; // test passed!
- }
- lastJournalLength = journalLength;
- }
- }
-
- /** @see <a href="https://github.com/JakeWharton/DiskLruCache/issues/28">Issue #28</a> */
- public void testRebuildJournalOnRepeatedEditsWithOpenAndClose() throws Exception {
- long lastJournalLength = 0;
- while (true) {
- long journalLength = journalFile.length();
- set("a", "a", "a");
- set("b", "b", "b");
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, Integer.MAX_VALUE);
- if (journalLength < lastJournalLength) {
- System.out.printf("Journal compacted from %s bytes to %s bytes\n",
- lastJournalLength, journalLength);
- break;
- }
- lastJournalLength = journalLength;
- }
- }
-
- public void testOpenCreatesDirectoryIfNecessary() throws Exception {
- cache.close();
- File dir = new File(javaTmpDir, "testOpenCreatesDirectoryIfNecessary");
- cache = DiskLruCache.open(dir, appVersion, 2, Integer.MAX_VALUE);
- set("A", "a", "a");
- assertTrue(new File(dir, "A.0").exists());
- assertTrue(new File(dir, "A.1").exists());
- assertTrue(new File(dir, "journal").exists());
- }
-
- public void testFileDeletedExternally() throws Exception {
- set("A", "a", "a");
- getCleanFile("A", 1).delete();
- assertNull(cache.get("A"));
- }
-
- public void testFileBecomesInaccessibleDuringReadResultsInIoException() throws Exception {
- set("A", "aaaaa", "a");
- DiskLruCache.Snapshot snapshot = cache.get("A");
- InputStream in = snapshot.getInputStream(0);
- assertEquals('a', in.read());
- mockOs.enqueueFault("read");
- try {
- in.read();
- fail();
- } catch (IOException expected) {
- }
- snapshot.close();
- }
-
- public void testFileBecomesInaccessibleDuringWriteIsSilentlyDiscarded() throws Exception {
- set("A", "a", "a");
- DiskLruCache.Editor editor = cache.edit("A");
- OutputStream out0 = editor.newOutputStream(0);
- out0.write('b');
- out0.close();
- OutputStream out1 = editor.newOutputStream(1);
- out1.write('c');
- mockOs.enqueueFault("write");
- out1.write('c'); // this doesn't throw...
- out1.close();
- editor.commit(); // ... but this will abort
- assertAbsent("A");
- }
-
- public void testEditSameVersion() throws Exception {
- set("A", "a", "a");
- DiskLruCache.Snapshot snapshot = cache.get("A");
- DiskLruCache.Editor editor = snapshot.edit();
- editor.set(1, "a2");
- editor.commit();
- assertValue("A", "a", "a2");
- }
-
- public void testEditSnapshotAfterChangeAborted() throws Exception {
- set("A", "a", "a");
- DiskLruCache.Snapshot snapshot = cache.get("A");
- DiskLruCache.Editor toAbort = snapshot.edit();
- toAbort.set(0, "b");
- toAbort.abort();
- DiskLruCache.Editor editor = snapshot.edit();
- editor.set(1, "a2");
- editor.commit();
- assertValue("A", "a", "a2");
- }
-
- public void testEditSnapshotAfterChangeCommitted() throws Exception {
- set("A", "a", "a");
- DiskLruCache.Snapshot snapshot = cache.get("A");
- DiskLruCache.Editor toAbort = snapshot.edit();
- toAbort.set(0, "b");
- toAbort.commit();
- assertNull(snapshot.edit());
- }
-
- public void testEditSinceEvicted() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
- set("A", "aa", "aaa"); // size 5
- DiskLruCache.Snapshot snapshot = cache.get("A");
- set("B", "bb", "bbb"); // size 5
- set("C", "cc", "ccc"); // size 5; will evict 'A'
- cache.flush();
- assertNull(snapshot.edit());
- }
-
- public void testEditSinceEvictedAndRecreated() throws Exception {
- cache.close();
- cache = DiskLruCache.open(cacheDir, appVersion, 2, 10);
- set("A", "aa", "aaa"); // size 5
- DiskLruCache.Snapshot snapshot = cache.get("A");
- set("B", "bb", "bbb"); // size 5
- set("C", "cc", "ccc"); // size 5; will evict 'A'
- set("A", "a", "aaaa"); // size 5; will evict 'B'
- cache.flush();
- assertNull(snapshot.edit());
- }
-
- private void assertJournalEquals(String... expectedBodyLines) throws Exception {
- List<String> expectedLines = new ArrayList<String>();
- expectedLines.add(MAGIC);
- expectedLines.add(VERSION_1);
- expectedLines.add("100");
- expectedLines.add("2");
- expectedLines.add("");
- expectedLines.addAll(Arrays.asList(expectedBodyLines));
- assertEquals(expectedLines, readJournalLines());
- }
-
- private void createJournal(String... bodyLines) throws Exception {
- createJournalWithHeader(MAGIC, VERSION_1, "100", "2", "", bodyLines);
- }
-
- private void createJournalWithHeader(String magic, String version, String appVersion,
- String valueCount, String blank, String... bodyLines) throws Exception {
- Writer writer = new FileWriter(journalFile);
- writer.write(magic + "\n");
- writer.write(version + "\n");
- writer.write(appVersion + "\n");
- writer.write(valueCount + "\n");
- writer.write(blank + "\n");
- for (String line : bodyLines) {
- writer.write(line);
- writer.write('\n');
- }
- writer.close();
- }
-
- private List<String> readJournalLines() throws Exception {
- List<String> result = new ArrayList<String>();
- BufferedReader reader = new BufferedReader(new FileReader(journalFile));
- String line;
- while ((line = reader.readLine()) != null) {
- result.add(line);
- }
- reader.close();
- return result;
- }
-
- private File getCleanFile(String key, int index) {
- return new File(cacheDir, key + "." + index);
- }
-
- private File getDirtyFile(String key, int index) {
- return new File(cacheDir, key + "." + index + ".tmp");
- }
-
- private String readFile(File file) throws Exception {
- Reader reader = new FileReader(file);
- StringWriter writer = new StringWriter();
- char[] buffer = new char[1024];
- int count;
- while ((count = reader.read(buffer)) != -1) {
- writer.write(buffer, 0, count);
- }
- reader.close();
- return writer.toString();
- }
-
- public void writeFile(File file, String content) throws Exception {
- FileWriter writer = new FileWriter(file);
- writer.write(content);
- writer.close();
- }
-
- private void assertInoperable(DiskLruCache.Editor editor) throws Exception {
- try {
- editor.getString(0);
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- editor.set(0, "A");
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- editor.newInputStream(0);
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- editor.newOutputStream(0);
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- editor.commit();
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- editor.abort();
- fail();
- } catch (IllegalStateException expected) {
- }
- }
-
- private void generateSomeGarbageFiles() throws Exception {
- File dir1 = new File(cacheDir, "dir1");
- File dir2 = new File(dir1, "dir2");
- writeFile(getCleanFile("g1", 0), "A");
- writeFile(getCleanFile("g1", 1), "B");
- writeFile(getCleanFile("g2", 0), "C");
- writeFile(getCleanFile("g2", 1), "D");
- writeFile(getCleanFile("g2", 1), "D");
- writeFile(new File(cacheDir, "otherFile0"), "E");
- dir1.mkdir();
- dir2.mkdir();
- writeFile(new File(dir2, "otherFile1"), "F");
- }
-
- private void assertGarbageFilesAllDeleted() throws Exception {
- assertFalse(getCleanFile("g1", 0).exists());
- assertFalse(getCleanFile("g1", 1).exists());
- assertFalse(getCleanFile("g2", 0).exists());
- assertFalse(getCleanFile("g2", 1).exists());
- assertFalse(new File(cacheDir, "otherFile0").exists());
- assertFalse(new File(cacheDir, "dir1").exists());
- }
-
- private void set(String key, String value0, String value1) throws Exception {
- DiskLruCache.Editor editor = cache.edit(key);
- editor.set(0, value0);
- editor.set(1, value1);
- editor.commit();
- }
-
- private void assertAbsent(String key) throws Exception {
- DiskLruCache.Snapshot snapshot = cache.get(key);
- if (snapshot != null) {
- snapshot.close();
- fail();
- }
- assertFalse(getCleanFile(key, 0).exists());
- assertFalse(getCleanFile(key, 1).exists());
- assertFalse(getDirtyFile(key, 0).exists());
- assertFalse(getDirtyFile(key, 1).exists());
- }
-
- private void assertValue(String key, String value0, String value1) throws Exception {
- DiskLruCache.Snapshot snapshot = cache.get(key);
- assertEquals(value0, snapshot.getString(0));
- assertEquals(value1, snapshot.getString(1));
- assertTrue(getCleanFile(key, 0).exists());
- assertTrue(getCleanFile(key, 1).exists());
- snapshot.close();
- }
-}
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 5e0e8c7..624c119 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -24,6 +24,7 @@
import java.net.InetUnixAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
+import java.util.Locale;
import junit.framework.TestCase;
import static libcore.io.OsConstants.*;
@@ -79,7 +80,7 @@
int requestLength = Libcore.os.read(clientFd, request, 0, request.length);
String s = new String(request, "UTF-8");
- byte[] response = s.toUpperCase().getBytes("UTF-8");
+ byte[] response = s.toUpperCase(Locale.ROOT).getBytes("UTF-8");
Libcore.os.write(clientFd, response, 0, response.length);
Libcore.os.close(clientFd);
@@ -103,7 +104,7 @@
byte[] response = new byte[request.length];
assertEquals(response.length, Libcore.os.read(clientFd, response, 0, response.length));
- assertEquals(string.toUpperCase(), new String(response, "UTF-8"));
+ assertEquals(string.toUpperCase(Locale.ROOT), new String(response, "UTF-8"));
Libcore.os.close(clientFd);
}
diff --git a/luni/src/test/java/libcore/io/StrictLineReaderTest.java b/luni/src/test/java/libcore/io/StrictLineReaderTest.java
index d5d3381..db88a6b 100644
--- a/luni/src/test/java/libcore/io/StrictLineReaderTest.java
+++ b/luni/src/test/java/libcore/io/StrictLineReaderTest.java
@@ -23,7 +23,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStream;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
public class StrictLineReaderTest extends TestCase {
@@ -31,7 +31,7 @@
try {
// Testing with LineReader buffer capacity 32 to check some corner cases.
StrictLineReader lineReader = new StrictLineReader(createTestInputStream(), 32,
- Charsets.US_ASCII);
+ StandardCharsets.US_ASCII);
InputStream refStream = createTestInputStream();
while (true) {
try {
@@ -81,4 +81,3 @@
).getBytes());
}
}
-
diff --git a/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java b/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
index 7a0d5fc..004fe76 100644
--- a/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
+++ b/luni/src/test/java/libcore/java/io/OldAndroidInputStreamReaderTest.java
@@ -38,7 +38,7 @@
assertEquals('A', x);
char[] c = new char[26];
x = a.read(c, 0, 26);
- assertTrue(a.getEncoding().equalsIgnoreCase("ISO8859_1"));
+ assertEquals("ISO-8859-1", a.getEncoding());
assertEquals(26, x);
assertEquals("bCdEfGhIjKlMnOpQrStUvWxYzX", String.valueOf(c));
} finally {
@@ -58,7 +58,7 @@
InputStreamReader a = new InputStreamReader(aa);
try {
- assertEquals("UTF8", a.getEncoding());
+ assertEquals("UTF-8", a.getEncoding());
int x = a.read();
assertEquals('A', x);
diff --git a/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java b/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
index de559ff..b4d91e1 100644
--- a/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
+++ b/luni/src/test/java/libcore/java/io/OldAndroidOutputStreamWriterTest.java
@@ -35,7 +35,7 @@
// We have to flush the OutputStreamWriter to guarantee
// that the results will appear in the underlying OutputStream
a.flush();
- assertEquals("ISO8859_1", a.getEncoding());
+ assertEquals("ISO-8859-1", a.getEncoding());
assertEquals(5, aa.size());
assertEquals("AbCdA", aa.toString());
} finally {
diff --git a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
index 214c1b2..986c672 100644
--- a/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
+++ b/luni/src/test/java/libcore/java/io/OldBufferedReaderTest.java
@@ -19,8 +19,13 @@
import java.io.BufferedReader;
import java.io.CharArrayReader;
+import java.io.InputStreamReader;
import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
import java.io.PipedReader;
+import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import tests.support.Support_ASimpleReader;
@@ -318,4 +323,79 @@
} catch (Exception e) {
}
}
+
+ public void test_readLine_all_line_endings() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r2\n3\r\n4"));
+ assertEquals("1", r.readLine());
+ assertEquals("2", r.readLine());
+ assertEquals("3", r.readLine());
+ assertEquals("4", r.readLine());
+ assertNull(r.readLine());
+ }
+
+ public void test_readLine_interaction_with_read() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+ assertEquals('1', r.read());
+ assertEquals('\r', r.read());
+ assertEquals("", r.readLine()); // The '\r' we read() didn't count.
+ assertEquals("2", r.readLine());
+ assertNull(r.readLine());
+ }
+
+ public void test_readLine_interaction_with_array_read_1() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+ assertEquals(2, r.read(new char[2], 0, 2));
+ assertEquals("", r.readLine()); // The '\r' we read() didn't count.
+ assertEquals("2", r.readLine());
+ assertNull(r.readLine());
+ }
+
+ public void test_readLine_interaction_with_array_read_2() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+ assertEquals("1", r.readLine());
+ char[] chars = new char[1];
+ assertEquals(1, r.read(chars, 0, 1)); // This read skips the '\n'.
+ assertEquals('2', chars[0]);
+ assertNull(r.readLine());
+ }
+
+ public void test_readLine_interaction_with_skip() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r\n2"));
+ assertEquals(2, r.skip(2));
+ assertEquals("", r.readLine()); // The '\r' we skip()ed didn't count.
+ assertEquals("2", r.readLine());
+ assertNull(r.readLine());
+ }
+
+ public void test_readLine_interaction_with_mark_and_reset() throws Exception {
+ BufferedReader r = new BufferedReader(new StringReader("1\r\n2\n3"));
+ assertEquals("1", r.readLine());
+ r.mark(256);
+ assertEquals('2', r.read()); // This read skips the '\n'.
+ assertEquals("", r.readLine());
+ r.reset(); // Now we're back half-way through the "\r\n".
+ assertEquals("2", r.readLine());
+ assertEquals("3", r.readLine());
+ assertNull(r.readLine());
+ }
+
+ public void test_8778372() throws Exception {
+ final PipedInputStream pis = new PipedInputStream();
+ final PipedOutputStream pos = new PipedOutputStream(pis);
+ final Thread t = new Thread() {
+ @Override public void run() {
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(pos));
+ pw.print("hello, world\r");
+ pw.flush();
+ try {
+ Thread.sleep(2*60*1000);
+ } catch (InterruptedException ex) {
+ fail();
+ }
+ }
+ };
+ t.start();
+ BufferedReader br = new BufferedReader(new InputStreamReader(pis));
+ assertEquals("hello, world", br.readLine());
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/CharacterTest.java b/luni/src/test/java/libcore/java/lang/CharacterTest.java
index 9438f20..48284d6 100644
--- a/luni/src/test/java/libcore/java/lang/CharacterTest.java
+++ b/luni/src/test/java/libcore/java/lang/CharacterTest.java
@@ -16,100 +16,251 @@
package libcore.java.lang;
+import java.lang.reflect.Method;
+
public class CharacterTest extends junit.framework.TestCase {
- public void test_valueOfC() {
- // The JLS requires caching for chars between "\u0000 to \u007f":
- // http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7
- // Harmony caches 0-512 and tests for this behavior, so we suppress that test and use this.
- for (char c = '\u0000'; c <= '\u007f'; ++c) {
- Character e = new Character(c);
- Character a = Character.valueOf(c);
- assertEquals(e, a);
- assertSame(Character.valueOf(c), Character.valueOf(c));
- }
- for (int c = '\u0080'; c <= Character.MAX_VALUE; ++c) {
- assertEquals(new Character((char) c), Character.valueOf((char) c));
- }
+ public void test_valueOfC() {
+ // The JLS requires caching for chars between "\u0000 to \u007f":
+ // http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.1.7
+ // Harmony caches 0-512 and tests for this behavior, so we suppress that test and use this.
+ for (char c = '\u0000'; c <= '\u007f'; ++c) {
+ Character e = new Character(c);
+ Character a = Character.valueOf(c);
+ assertEquals(e, a);
+ assertSame(Character.valueOf(c), Character.valueOf(c));
+ }
+ for (int c = '\u0080'; c <= Character.MAX_VALUE; ++c) {
+ assertEquals(new Character((char) c), Character.valueOf((char) c));
+ }
+ }
+
+ public void test_isBmpCodePoint() throws Exception {
+ assertTrue(Character.isBmpCodePoint(0x0000));
+ assertTrue(Character.isBmpCodePoint(0x0666));
+ assertTrue(Character.isBmpCodePoint(0xffff));
+ assertFalse(Character.isBmpCodePoint(0x10000));
+ assertFalse(Character.isBmpCodePoint(-1));
+ assertFalse(Character.isBmpCodePoint(Integer.MAX_VALUE));
+ assertFalse(Character.isBmpCodePoint(Integer.MIN_VALUE));
+ }
+
+ public void test_isSurrogate() throws Exception {
+ assertFalse(Character.isSurrogate('\u0000'));
+ assertFalse(Character.isSurrogate('\u0666'));
+ assertFalse(Character.isSurrogate((char) (Character.MIN_SURROGATE - 1)));
+ for (char ch = Character.MIN_SURROGATE; ch <= Character.MAX_SURROGATE; ++ch) {
+ assertTrue(Character.isSurrogate(ch));
+ }
+ assertFalse(Character.isSurrogate((char) (Character.MAX_SURROGATE + 1)));
+ }
+
+ public void test_highSurrogate() throws Exception {
+ // The behavior for non-supplementary code points (like these two) is undefined.
+ // These are the obvious results if you don't do anything special.
+ assertEquals(0xd7c0, Character.highSurrogate(0x0000));
+ assertEquals(0xd7c1, Character.highSurrogate(0x0666));
+ // These two tests must pass, though.
+ assertEquals(0xd800, Character.highSurrogate(0x010000));
+ assertEquals(0xdbff, Character.highSurrogate(0x10ffff));
+ }
+
+ public void test_lowSurrogate() throws Exception {
+ // The behavior for non-supplementary code points (like these two) is undefined.
+ // These are the obvious results if you don't do anything special.
+ assertEquals(0xdc00, Character.lowSurrogate(0x0000));
+ assertEquals(0xde66, Character.lowSurrogate(0x0666));
+ // These two tests must pass, though.
+ assertEquals(0xdc00, Character.lowSurrogate(0x010000));
+ assertEquals(0xdfff, Character.lowSurrogate(0x10ffff));
+ }
+
+ public void test_getName() throws Exception {
+ // Character.getName requires the corresponding ICU data.
+ // Changed from "NULL" and "BELL" by Unicode 49.2
+ assertEquals("<control-0000>", Character.getName(0x0000));
+ assertEquals("<control-0007>", Character.getName(0x0007));
+ assertEquals("LATIN SMALL LETTER L", Character.getName('l'));
+ // This changed name from Unicode 1.0. Used to be "OPENING...".
+ assertEquals("LEFT CURLY BRACKET", Character.getName('{'));
+ assertEquals("ARABIC-INDIC DIGIT SIX", Character.getName(0x0666));
+ assertEquals("LINEAR B SYLLABLE B008 A", Character.getName(0x010000));
+
+ // Some private use code points.
+ assertEquals("PRIVATE USE AREA E000", Character.getName(0xe000));
+ assertEquals("SUPPLEMENTARY PRIVATE USE AREA A F0000", Character.getName(0xf0000));
+
+ // An unassigned code point.
+ assertNull(Character.getName(0x10ffff));
+
+ try {
+ Character.getName(-1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ Character.getName(Integer.MAX_VALUE);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ Character.getName(Integer.MIN_VALUE);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void test_compare() throws Exception {
+ assertEquals(0, Character.compare('a', 'a'));
+ assertTrue(Character.compare('a', 'b') < 0);
+ assertTrue(Character.compare('b', 'a') > 0);
+ }
+
+ public void test_UnicodeBlock_all() throws Exception {
+ for (int i = 0; i <= 0x100000; ++i) {
+ Character.UnicodeBlock.of(i);
+ }
+ }
+
+ public void test_UnicodeBlock_of() throws Exception {
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.of(1));
+ assertEquals(Character.UnicodeBlock.HANGUL_JAMO, Character.UnicodeBlock.of(0x1100));
+ assertEquals(Character.UnicodeBlock.CYPRIOT_SYLLABARY, Character.UnicodeBlock.of(0x10800));
+ assertEquals(Character.UnicodeBlock.VARIATION_SELECTORS_SUPPLEMENT, Character.UnicodeBlock.of(0xe0100));
+ // Unicode 4.1.
+ assertEquals(Character.UnicodeBlock.ANCIENT_GREEK_MUSICAL_NOTATION, Character.UnicodeBlock.of(0x1d200));
+ // Unicode 5.0.
+ assertEquals(Character.UnicodeBlock.NKO, Character.UnicodeBlock.of(0x07c0));
+ // Unicode 5.1.
+ assertEquals(Character.UnicodeBlock.SUNDANESE, Character.UnicodeBlock.of(0x1b80));
+ // Unicode 5.2.
+ assertEquals(Character.UnicodeBlock.SAMARITAN, Character.UnicodeBlock.of(0x0800));
+ // Unicode 6.0.
+ assertEquals(Character.UnicodeBlock.MANDAIC, Character.UnicodeBlock.of(0x0840));
+ }
+
+ public void test_UnicodeBlock_forName() throws Exception {
+ // No negative tests here because icu4c is more lenient than the RI;
+ // we'd allow "basic-latin", and "hangul jamo extended b", for example.
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("basic latin"));
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BaSiC LaTiN"));
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BasicLatin"));
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("BASIC_LATIN"));
+ assertEquals(Character.UnicodeBlock.BASIC_LATIN, Character.UnicodeBlock.forName("basic_LATIN"));
+
+ assertEquals(Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B, Character.UnicodeBlock.forName("HANGUL_JAMO_EXTENDED_B"));
+ assertEquals(Character.UnicodeBlock.HANGUL_JAMO_EXTENDED_B, Character.UnicodeBlock.forName("HANGUL JAMO EXTENDED-B"));
+
+ // Failure cases.
+ try {
+ Character.UnicodeBlock.forName(null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+ try {
+ Character.UnicodeBlock.forName("this unicode block does not exist");
+ fail();
+ } catch (IllegalArgumentException expected) {
}
- public void test_isBmpCodePoint() throws Exception {
- assertTrue(Character.isBmpCodePoint(0x0000));
- assertTrue(Character.isBmpCodePoint(0x0666));
- assertTrue(Character.isBmpCodePoint(0xffff));
- assertFalse(Character.isBmpCodePoint(0x10000));
- assertFalse(Character.isBmpCodePoint(-1));
- assertFalse(Character.isBmpCodePoint(Integer.MAX_VALUE));
- assertFalse(Character.isBmpCodePoint(Integer.MIN_VALUE));
+ // Renamed blocks.
+ assertEquals(Character.UnicodeBlock.GREEK, Character.UnicodeBlock.forName("Greek"));
+ assertEquals(Character.UnicodeBlock.GREEK, Character.UnicodeBlock.forName("Greek And Coptic"));
+ assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Marks For Symbols"));
+ assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Diacritical Marks For Symbols"));
+ assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("COMBINING_MARKS_FOR_SYMBOLS"));
+ assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("Combining Marks for Symbols"));
+ assertEquals(Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS, Character.UnicodeBlock.forName("CombiningMarksforSymbols"));
+ assertEquals(Character.UnicodeBlock.CYRILLIC_SUPPLEMENTARY, Character.UnicodeBlock.forName("Cyrillic Supplementary"));
+ assertEquals(Character.UnicodeBlock.CYRILLIC_SUPPLEMENTARY, Character.UnicodeBlock.forName("Cyrillic Supplement"));
+ }
+
+ public void test_isAlphabetic() throws Exception {
+ assertTrue(Character.isAlphabetic('A'));
+ assertTrue(Character.isAlphabetic('a'));
+ assertFalse(Character.isAlphabetic('1'));
+ assertTrue(Character.isAlphabetic(0x113c)); // Hangul j
+ }
+
+ public void test_isIdeographic() throws Exception {
+ assertFalse(Character.isIdeographic('A'));
+ assertFalse(Character.isIdeographic('a'));
+ assertFalse(Character.isIdeographic('1'));
+ assertFalse(Character.isIdeographic(0x113c)); // Hangul j
+
+ assertTrue(Character.isIdeographic(0x4db5));
+ assertTrue(Character.isIdeographic(0x2f999));
+ assertFalse(Character.isIdeographic(0x2f99)); // Kangxi radical shell
+ }
+
+ // http://b/9690863
+ public void test_isDigit_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isDigit" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isDigit(i));
}
+ }
- public void test_isSurrogate() throws Exception {
- assertFalse(Character.isSurrogate('\u0000'));
- assertFalse(Character.isSurrogate('\u0666'));
- assertFalse(Character.isSurrogate((char) (Character.MIN_SURROGATE - 1)));
- for (char ch = Character.MIN_SURROGATE; ch <= Character.MAX_SURROGATE; ++ch) {
- assertTrue(Character.isSurrogate(ch));
- }
- assertFalse(Character.isSurrogate((char) (Character.MAX_SURROGATE + 1)));
+ // http://b/9690863
+ public void test_isIdentifierIgnorable_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isIdentifierIgnorable" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isIdentifierIgnorable(i));
}
+ }
- public void test_highSurrogate() throws Exception {
- // The behavior for non-supplementary code points (like these two) is undefined.
- // These are the obvious results if you don't do anything special.
- assertEquals(0xd7c0, Character.highSurrogate(0x0000));
- assertEquals(0xd7c1, Character.highSurrogate(0x0666));
- // These two tests must pass, though.
- assertEquals(0xd800, Character.highSurrogate(0x010000));
- assertEquals(0xdbff, Character.highSurrogate(0x10ffff));
+ // http://b/9690863
+ public void test_isLetter_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isLetter" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isLetter(i));
}
+ }
- public void test_lowSurrogate() throws Exception {
- // The behavior for non-supplementary code points (like these two) is undefined.
- // These are the obvious results if you don't do anything special.
- assertEquals(0xdc00, Character.lowSurrogate(0x0000));
- assertEquals(0xde66, Character.lowSurrogate(0x0666));
- // These two tests must pass, though.
- assertEquals(0xdc00, Character.lowSurrogate(0x010000));
- assertEquals(0xdfff, Character.lowSurrogate(0x10ffff));
+ // http://b/9690863
+ public void test_isLetterOrDigit_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isLetterOrDigit" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isLetterOrDigit(i));
}
+ }
- public void test_getName() throws Exception {
- // Character.getName requires the corresponding ICU data.
- // Changed from "NULL" and "BELL" by Unicode 49.2
- assertEquals("<control-0000>", Character.getName(0x0000));
- assertEquals("<control-0007>", Character.getName(0x0007));
- assertEquals("LATIN SMALL LETTER L", Character.getName('l'));
- // This changed name from Unicode 1.0. Used to be "OPENING...".
- assertEquals("LEFT CURLY BRACKET", Character.getName('{'));
- assertEquals("ARABIC-INDIC DIGIT SIX", Character.getName(0x0666));
- assertEquals("LINEAR B SYLLABLE B008 A", Character.getName(0x010000));
-
- // Some private use code points.
- assertEquals("PRIVATE USE AREA E000", Character.getName(0xe000));
- assertEquals("SUPPLEMENTARY PRIVATE USE AREA A F0000", Character.getName(0xf0000));
-
- // An unassigned code point.
- assertNull(Character.getName(0x10ffff));
-
- try {
- Character.getName(-1);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- try {
- Character.getName(Integer.MAX_VALUE);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- try {
- Character.getName(Integer.MIN_VALUE);
- fail();
- } catch (IllegalArgumentException expected) {
- }
+ // http://b/9690863
+ public void test_isLowerCase_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isLowerCase" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isLowerCase(i));
}
+ }
- public void test_compare() throws Exception {
- assertEquals(0, Character.compare('a', 'a'));
- assertTrue(Character.compare('a', 'b') < 0);
- assertTrue(Character.compare('b', 'a') > 0);
+ // http://b/9690863
+ public void test_isSpaceChar_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isSpaceChar" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ if((Boolean) m.invoke(null, i) != Character.isSpaceChar(i)) System.out.println(i);
}
+ }
+
+ // http://b/9690863
+ public void test_isUpperCase_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isUpperCase" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isUpperCase(i));
+ }
+ }
+
+ // http://b/9690863
+ public void test_isWhitespace_against_icu4c() throws Exception {
+ Method m = Character.class.getDeclaredMethod("isWhitespace" + "Impl", int.class);
+ m.setAccessible(true);
+ for (int i = 0; i <= 0xffff; ++i) {
+ assertEquals(m.invoke(null, i), Character.isWhitespace(i));
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/StringTest.java b/luni/src/test/java/libcore/java/lang/StringTest.java
index 5aa596f..605fd63 100644
--- a/luni/src/test/java/libcore/java/lang/StringTest.java
+++ b/luni/src/test/java/libcore/java/lang/StringTest.java
@@ -341,4 +341,11 @@
// Our fast-path code in String should behave the same...
assertEquals(expected, new String(bytes, "UTF-8"));
}
+
+ // https://code.google.com/p/android/issues/detail?id=55129
+ public void test_55129() throws Exception {
+ assertEquals("-h-e-l-l-o- -w-o-r-l-d-", "hello world".replace("", "-"));
+ assertEquals("-w-o-r-l-d-", "hello world".substring(6).replace("", "-"));
+ assertEquals("-*-w-*-o-*-r-*-l-*-d-*-", "hello world".substring(6).replace("", "-*-"));
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/ThrowableTest.java b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
index 1906784..7c8ae66 100644
--- a/luni/src/test/java/libcore/java/lang/ThrowableTest.java
+++ b/luni/src/test/java/libcore/java/lang/ThrowableTest.java
@@ -38,10 +38,35 @@
}
}
+ public void testNonWritableStackTrace() {
+ try {
+ // The 4th argument, writableStackTrace, is false...
+ throw new SuppressionsThrowable("hi", null, true, false);
+ } catch (Throwable th) {
+ assertEquals("hi", th.getMessage());
+
+ // We see an empty stack trace.
+ assertEquals(0, th.getStackTrace().length);
+
+ // setStackTrace is a no-op.
+ th.setStackTrace(new StackTraceElement[] { new StackTraceElement("c", "m", "f", -2) });
+ assertEquals(0, th.getStackTrace().length);
+
+ // fillInStackTrace is a no-op.
+ th.fillInStackTrace();
+ assertEquals(0, th.getStackTrace().length);
+
+ // It's still possible to print an exception with writableStackTrace == false.
+ th.printStackTrace(new PrintWriter(new StringWriter()));
+ }
+ }
+
private static class SuppressionsThrowable extends Throwable {
+ private static final long serialVersionUID = 202649043897209143L;
+
public SuppressionsThrowable(String detailMessage, Throwable throwable,
- boolean enableSuppression) {
- super(detailMessage, throwable, enableSuppression);
+ boolean enableSuppression, boolean writableStackTrace) {
+ super(detailMessage, throwable, enableSuppression, writableStackTrace);
}
}
@@ -78,7 +103,7 @@
}
public void testAddSuppressedWithSuppressionDisabled() {
- Throwable throwable = new SuppressionsThrowable("foo", null, false);
+ Throwable throwable = new SuppressionsThrowable("foo", null, false, true);
assertSuppressed(throwable);
throwable.addSuppressed(new Throwable());
assertSuppressed(throwable);
@@ -246,7 +271,7 @@
+ "4696f6e737400104c6a6176612f7574696c2f4c6973743b787070740003666f6f7572001e5b4c6a6"
+ "176612e6c616e672e537461636b5472616365456c656d656e743b02462a3c3cfd223902000078700"
+ "00000007078";
- Throwable throwable = new SuppressionsThrowable("foo", null, false);
+ Throwable throwable = new SuppressionsThrowable("foo", null, false, true);
throwable.setStackTrace(new StackTraceElement[0]);
new SerializationTester<Throwable>(throwable, s) {
@Override protected boolean equals(Throwable a, Throwable b) {
@@ -275,7 +300,7 @@
+ "0cb5ef71e0200014c0001637400164c6a6176612f7574696c2f436f6c6c656374696f6e3b7870737"
+ "200136a6176612e7574696c2e41727261794c6973747881d21d99c7619d03000149000473697a657"
+ "870000000007704000000007871007e000f78";
- Throwable throwable = new SuppressionsThrowable("foo", null, true);
+ Throwable throwable = new SuppressionsThrowable("foo", null, true, true);
throwable.setStackTrace(new StackTraceElement[0]);
new SerializationTester<Throwable>(throwable, s) {
@Override protected boolean equals(Throwable a, Throwable b) {
diff --git a/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
new file mode 100644
index 0000000..60e294b
--- /dev/null
+++ b/luni/src/test/java/libcore/java/lang/reflect/Annotations57649Test.java
@@ -0,0 +1,12031 @@
+package libcore.java.lang.reflect;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import junit.framework.TestCase;
+
+public final class Annotations57649Test extends TestCase {
+ // https://code.google.com/p/android/issues/detail?id=57649
+ public void test57649() throws Exception {
+ Thread a = runTest(A.class);
+ Thread b = runTest(B.class);
+ a.join();
+ b.join();
+ }
+
+ private static Thread runTest(final Class<?> c) {
+ Thread t = new Thread(new Runnable() {
+ @Override public void run() {
+ assertEquals(3000, c.getAnnotations().length);
+ }
+ }, c.toString());
+ t.start();
+ return t;
+ }
+
+ @Retention(RetentionPolicy.RUNTIME) @interface A0 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A3 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A4 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A5 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A6 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A7 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A8 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A9 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A10 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A11 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A12 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A13 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A14 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A15 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A16 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A17 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A18 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A19 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A20 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A21 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A22 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A23 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A24 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A25 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A26 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A27 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A28 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A29 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A30 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A31 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A32 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A33 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A34 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A35 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A36 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A37 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A38 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A39 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A40 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A41 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A42 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A43 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A44 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A45 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A46 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A47 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A48 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A49 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A50 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A51 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A52 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A53 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A54 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A55 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A56 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A57 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A58 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A59 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A60 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A61 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A62 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A63 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A64 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A65 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A66 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A67 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A68 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A69 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A70 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A71 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A72 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A73 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A74 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A75 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A76 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A77 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A78 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A79 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A80 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A81 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A82 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A83 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A84 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A85 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A86 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A87 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A88 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A89 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A90 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A91 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A92 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A93 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A94 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A95 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A96 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A97 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A98 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A99 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A999 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1000 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1001 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1002 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1003 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1004 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1005 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1006 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1007 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1008 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1009 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1010 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1011 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1012 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1013 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1014 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1015 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1016 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1017 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1018 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1019 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1020 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1021 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1022 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1023 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1024 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1025 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1026 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1027 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1028 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1029 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1030 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1031 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1032 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1033 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1034 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1035 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1036 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1037 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1038 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1039 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1040 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1041 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1042 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1043 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1044 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1045 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1046 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1047 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1048 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1049 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1050 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1051 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1052 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1053 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1054 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1055 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1056 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1057 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1058 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1059 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1060 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1061 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1062 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1063 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1064 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1065 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1066 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1067 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1068 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1069 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1070 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1071 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1072 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1073 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1074 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1075 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1076 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1077 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1078 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1079 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1080 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1081 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1082 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1083 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1084 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1085 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1086 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1087 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1088 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1089 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1090 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1091 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1092 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1093 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1094 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1095 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1096 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1097 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1098 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1099 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A1999 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2000 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2001 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2002 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2003 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2004 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2005 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2006 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2007 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2008 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2009 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2010 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2011 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2012 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2013 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2014 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2015 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2016 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2017 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2018 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2019 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2020 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2021 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2022 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2023 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2024 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2025 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2026 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2027 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2028 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2029 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2030 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2031 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2032 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2033 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2034 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2035 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2036 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2037 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2038 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2039 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2040 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2041 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2042 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2043 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2044 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2045 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2046 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2047 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2048 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2049 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2050 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2051 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2052 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2053 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2054 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2055 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2056 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2057 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2058 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2059 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2060 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2061 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2062 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2063 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2064 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2065 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2066 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2067 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2068 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2069 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2070 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2071 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2072 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2073 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2074 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2075 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2076 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2077 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2078 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2079 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2080 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2081 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2082 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2083 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2084 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2085 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2086 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2087 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2088 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2089 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2090 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2091 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2092 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2093 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2094 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2095 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2096 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2097 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2098 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2099 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface A2999 {}
+
+ @A0
+ @A1
+ @A2
+ @A3
+ @A4
+ @A5
+ @A6
+ @A7
+ @A8
+ @A9
+ @A10
+ @A11
+ @A12
+ @A13
+ @A14
+ @A15
+ @A16
+ @A17
+ @A18
+ @A19
+ @A20
+ @A21
+ @A22
+ @A23
+ @A24
+ @A25
+ @A26
+ @A27
+ @A28
+ @A29
+ @A30
+ @A31
+ @A32
+ @A33
+ @A34
+ @A35
+ @A36
+ @A37
+ @A38
+ @A39
+ @A40
+ @A41
+ @A42
+ @A43
+ @A44
+ @A45
+ @A46
+ @A47
+ @A48
+ @A49
+ @A50
+ @A51
+ @A52
+ @A53
+ @A54
+ @A55
+ @A56
+ @A57
+ @A58
+ @A59
+ @A60
+ @A61
+ @A62
+ @A63
+ @A64
+ @A65
+ @A66
+ @A67
+ @A68
+ @A69
+ @A70
+ @A71
+ @A72
+ @A73
+ @A74
+ @A75
+ @A76
+ @A77
+ @A78
+ @A79
+ @A80
+ @A81
+ @A82
+ @A83
+ @A84
+ @A85
+ @A86
+ @A87
+ @A88
+ @A89
+ @A90
+ @A91
+ @A92
+ @A93
+ @A94
+ @A95
+ @A96
+ @A97
+ @A98
+ @A99
+ @A100
+ @A101
+ @A102
+ @A103
+ @A104
+ @A105
+ @A106
+ @A107
+ @A108
+ @A109
+ @A110
+ @A111
+ @A112
+ @A113
+ @A114
+ @A115
+ @A116
+ @A117
+ @A118
+ @A119
+ @A120
+ @A121
+ @A122
+ @A123
+ @A124
+ @A125
+ @A126
+ @A127
+ @A128
+ @A129
+ @A130
+ @A131
+ @A132
+ @A133
+ @A134
+ @A135
+ @A136
+ @A137
+ @A138
+ @A139
+ @A140
+ @A141
+ @A142
+ @A143
+ @A144
+ @A145
+ @A146
+ @A147
+ @A148
+ @A149
+ @A150
+ @A151
+ @A152
+ @A153
+ @A154
+ @A155
+ @A156
+ @A157
+ @A158
+ @A159
+ @A160
+ @A161
+ @A162
+ @A163
+ @A164
+ @A165
+ @A166
+ @A167
+ @A168
+ @A169
+ @A170
+ @A171
+ @A172
+ @A173
+ @A174
+ @A175
+ @A176
+ @A177
+ @A178
+ @A179
+ @A180
+ @A181
+ @A182
+ @A183
+ @A184
+ @A185
+ @A186
+ @A187
+ @A188
+ @A189
+ @A190
+ @A191
+ @A192
+ @A193
+ @A194
+ @A195
+ @A196
+ @A197
+ @A198
+ @A199
+ @A200
+ @A201
+ @A202
+ @A203
+ @A204
+ @A205
+ @A206
+ @A207
+ @A208
+ @A209
+ @A210
+ @A211
+ @A212
+ @A213
+ @A214
+ @A215
+ @A216
+ @A217
+ @A218
+ @A219
+ @A220
+ @A221
+ @A222
+ @A223
+ @A224
+ @A225
+ @A226
+ @A227
+ @A228
+ @A229
+ @A230
+ @A231
+ @A232
+ @A233
+ @A234
+ @A235
+ @A236
+ @A237
+ @A238
+ @A239
+ @A240
+ @A241
+ @A242
+ @A243
+ @A244
+ @A245
+ @A246
+ @A247
+ @A248
+ @A249
+ @A250
+ @A251
+ @A252
+ @A253
+ @A254
+ @A255
+ @A256
+ @A257
+ @A258
+ @A259
+ @A260
+ @A261
+ @A262
+ @A263
+ @A264
+ @A265
+ @A266
+ @A267
+ @A268
+ @A269
+ @A270
+ @A271
+ @A272
+ @A273
+ @A274
+ @A275
+ @A276
+ @A277
+ @A278
+ @A279
+ @A280
+ @A281
+ @A282
+ @A283
+ @A284
+ @A285
+ @A286
+ @A287
+ @A288
+ @A289
+ @A290
+ @A291
+ @A292
+ @A293
+ @A294
+ @A295
+ @A296
+ @A297
+ @A298
+ @A299
+ @A300
+ @A301
+ @A302
+ @A303
+ @A304
+ @A305
+ @A306
+ @A307
+ @A308
+ @A309
+ @A310
+ @A311
+ @A312
+ @A313
+ @A314
+ @A315
+ @A316
+ @A317
+ @A318
+ @A319
+ @A320
+ @A321
+ @A322
+ @A323
+ @A324
+ @A325
+ @A326
+ @A327
+ @A328
+ @A329
+ @A330
+ @A331
+ @A332
+ @A333
+ @A334
+ @A335
+ @A336
+ @A337
+ @A338
+ @A339
+ @A340
+ @A341
+ @A342
+ @A343
+ @A344
+ @A345
+ @A346
+ @A347
+ @A348
+ @A349
+ @A350
+ @A351
+ @A352
+ @A353
+ @A354
+ @A355
+ @A356
+ @A357
+ @A358
+ @A359
+ @A360
+ @A361
+ @A362
+ @A363
+ @A364
+ @A365
+ @A366
+ @A367
+ @A368
+ @A369
+ @A370
+ @A371
+ @A372
+ @A373
+ @A374
+ @A375
+ @A376
+ @A377
+ @A378
+ @A379
+ @A380
+ @A381
+ @A382
+ @A383
+ @A384
+ @A385
+ @A386
+ @A387
+ @A388
+ @A389
+ @A390
+ @A391
+ @A392
+ @A393
+ @A394
+ @A395
+ @A396
+ @A397
+ @A398
+ @A399
+ @A400
+ @A401
+ @A402
+ @A403
+ @A404
+ @A405
+ @A406
+ @A407
+ @A408
+ @A409
+ @A410
+ @A411
+ @A412
+ @A413
+ @A414
+ @A415
+ @A416
+ @A417
+ @A418
+ @A419
+ @A420
+ @A421
+ @A422
+ @A423
+ @A424
+ @A425
+ @A426
+ @A427
+ @A428
+ @A429
+ @A430
+ @A431
+ @A432
+ @A433
+ @A434
+ @A435
+ @A436
+ @A437
+ @A438
+ @A439
+ @A440
+ @A441
+ @A442
+ @A443
+ @A444
+ @A445
+ @A446
+ @A447
+ @A448
+ @A449
+ @A450
+ @A451
+ @A452
+ @A453
+ @A454
+ @A455
+ @A456
+ @A457
+ @A458
+ @A459
+ @A460
+ @A461
+ @A462
+ @A463
+ @A464
+ @A465
+ @A466
+ @A467
+ @A468
+ @A469
+ @A470
+ @A471
+ @A472
+ @A473
+ @A474
+ @A475
+ @A476
+ @A477
+ @A478
+ @A479
+ @A480
+ @A481
+ @A482
+ @A483
+ @A484
+ @A485
+ @A486
+ @A487
+ @A488
+ @A489
+ @A490
+ @A491
+ @A492
+ @A493
+ @A494
+ @A495
+ @A496
+ @A497
+ @A498
+ @A499
+ @A500
+ @A501
+ @A502
+ @A503
+ @A504
+ @A505
+ @A506
+ @A507
+ @A508
+ @A509
+ @A510
+ @A511
+ @A512
+ @A513
+ @A514
+ @A515
+ @A516
+ @A517
+ @A518
+ @A519
+ @A520
+ @A521
+ @A522
+ @A523
+ @A524
+ @A525
+ @A526
+ @A527
+ @A528
+ @A529
+ @A530
+ @A531
+ @A532
+ @A533
+ @A534
+ @A535
+ @A536
+ @A537
+ @A538
+ @A539
+ @A540
+ @A541
+ @A542
+ @A543
+ @A544
+ @A545
+ @A546
+ @A547
+ @A548
+ @A549
+ @A550
+ @A551
+ @A552
+ @A553
+ @A554
+ @A555
+ @A556
+ @A557
+ @A558
+ @A559
+ @A560
+ @A561
+ @A562
+ @A563
+ @A564
+ @A565
+ @A566
+ @A567
+ @A568
+ @A569
+ @A570
+ @A571
+ @A572
+ @A573
+ @A574
+ @A575
+ @A576
+ @A577
+ @A578
+ @A579
+ @A580
+ @A581
+ @A582
+ @A583
+ @A584
+ @A585
+ @A586
+ @A587
+ @A588
+ @A589
+ @A590
+ @A591
+ @A592
+ @A593
+ @A594
+ @A595
+ @A596
+ @A597
+ @A598
+ @A599
+ @A600
+ @A601
+ @A602
+ @A603
+ @A604
+ @A605
+ @A606
+ @A607
+ @A608
+ @A609
+ @A610
+ @A611
+ @A612
+ @A613
+ @A614
+ @A615
+ @A616
+ @A617
+ @A618
+ @A619
+ @A620
+ @A621
+ @A622
+ @A623
+ @A624
+ @A625
+ @A626
+ @A627
+ @A628
+ @A629
+ @A630
+ @A631
+ @A632
+ @A633
+ @A634
+ @A635
+ @A636
+ @A637
+ @A638
+ @A639
+ @A640
+ @A641
+ @A642
+ @A643
+ @A644
+ @A645
+ @A646
+ @A647
+ @A648
+ @A649
+ @A650
+ @A651
+ @A652
+ @A653
+ @A654
+ @A655
+ @A656
+ @A657
+ @A658
+ @A659
+ @A660
+ @A661
+ @A662
+ @A663
+ @A664
+ @A665
+ @A666
+ @A667
+ @A668
+ @A669
+ @A670
+ @A671
+ @A672
+ @A673
+ @A674
+ @A675
+ @A676
+ @A677
+ @A678
+ @A679
+ @A680
+ @A681
+ @A682
+ @A683
+ @A684
+ @A685
+ @A686
+ @A687
+ @A688
+ @A689
+ @A690
+ @A691
+ @A692
+ @A693
+ @A694
+ @A695
+ @A696
+ @A697
+ @A698
+ @A699
+ @A700
+ @A701
+ @A702
+ @A703
+ @A704
+ @A705
+ @A706
+ @A707
+ @A708
+ @A709
+ @A710
+ @A711
+ @A712
+ @A713
+ @A714
+ @A715
+ @A716
+ @A717
+ @A718
+ @A719
+ @A720
+ @A721
+ @A722
+ @A723
+ @A724
+ @A725
+ @A726
+ @A727
+ @A728
+ @A729
+ @A730
+ @A731
+ @A732
+ @A733
+ @A734
+ @A735
+ @A736
+ @A737
+ @A738
+ @A739
+ @A740
+ @A741
+ @A742
+ @A743
+ @A744
+ @A745
+ @A746
+ @A747
+ @A748
+ @A749
+ @A750
+ @A751
+ @A752
+ @A753
+ @A754
+ @A755
+ @A756
+ @A757
+ @A758
+ @A759
+ @A760
+ @A761
+ @A762
+ @A763
+ @A764
+ @A765
+ @A766
+ @A767
+ @A768
+ @A769
+ @A770
+ @A771
+ @A772
+ @A773
+ @A774
+ @A775
+ @A776
+ @A777
+ @A778
+ @A779
+ @A780
+ @A781
+ @A782
+ @A783
+ @A784
+ @A785
+ @A786
+ @A787
+ @A788
+ @A789
+ @A790
+ @A791
+ @A792
+ @A793
+ @A794
+ @A795
+ @A796
+ @A797
+ @A798
+ @A799
+ @A800
+ @A801
+ @A802
+ @A803
+ @A804
+ @A805
+ @A806
+ @A807
+ @A808
+ @A809
+ @A810
+ @A811
+ @A812
+ @A813
+ @A814
+ @A815
+ @A816
+ @A817
+ @A818
+ @A819
+ @A820
+ @A821
+ @A822
+ @A823
+ @A824
+ @A825
+ @A826
+ @A827
+ @A828
+ @A829
+ @A830
+ @A831
+ @A832
+ @A833
+ @A834
+ @A835
+ @A836
+ @A837
+ @A838
+ @A839
+ @A840
+ @A841
+ @A842
+ @A843
+ @A844
+ @A845
+ @A846
+ @A847
+ @A848
+ @A849
+ @A850
+ @A851
+ @A852
+ @A853
+ @A854
+ @A855
+ @A856
+ @A857
+ @A858
+ @A859
+ @A860
+ @A861
+ @A862
+ @A863
+ @A864
+ @A865
+ @A866
+ @A867
+ @A868
+ @A869
+ @A870
+ @A871
+ @A872
+ @A873
+ @A874
+ @A875
+ @A876
+ @A877
+ @A878
+ @A879
+ @A880
+ @A881
+ @A882
+ @A883
+ @A884
+ @A885
+ @A886
+ @A887
+ @A888
+ @A889
+ @A890
+ @A891
+ @A892
+ @A893
+ @A894
+ @A895
+ @A896
+ @A897
+ @A898
+ @A899
+ @A900
+ @A901
+ @A902
+ @A903
+ @A904
+ @A905
+ @A906
+ @A907
+ @A908
+ @A909
+ @A910
+ @A911
+ @A912
+ @A913
+ @A914
+ @A915
+ @A916
+ @A917
+ @A918
+ @A919
+ @A920
+ @A921
+ @A922
+ @A923
+ @A924
+ @A925
+ @A926
+ @A927
+ @A928
+ @A929
+ @A930
+ @A931
+ @A932
+ @A933
+ @A934
+ @A935
+ @A936
+ @A937
+ @A938
+ @A939
+ @A940
+ @A941
+ @A942
+ @A943
+ @A944
+ @A945
+ @A946
+ @A947
+ @A948
+ @A949
+ @A950
+ @A951
+ @A952
+ @A953
+ @A954
+ @A955
+ @A956
+ @A957
+ @A958
+ @A959
+ @A960
+ @A961
+ @A962
+ @A963
+ @A964
+ @A965
+ @A966
+ @A967
+ @A968
+ @A969
+ @A970
+ @A971
+ @A972
+ @A973
+ @A974
+ @A975
+ @A976
+ @A977
+ @A978
+ @A979
+ @A980
+ @A981
+ @A982
+ @A983
+ @A984
+ @A985
+ @A986
+ @A987
+ @A988
+ @A989
+ @A990
+ @A991
+ @A992
+ @A993
+ @A994
+ @A995
+ @A996
+ @A997
+ @A998
+ @A999
+ @A1000
+ @A1001
+ @A1002
+ @A1003
+ @A1004
+ @A1005
+ @A1006
+ @A1007
+ @A1008
+ @A1009
+ @A1010
+ @A1011
+ @A1012
+ @A1013
+ @A1014
+ @A1015
+ @A1016
+ @A1017
+ @A1018
+ @A1019
+ @A1020
+ @A1021
+ @A1022
+ @A1023
+ @A1024
+ @A1025
+ @A1026
+ @A1027
+ @A1028
+ @A1029
+ @A1030
+ @A1031
+ @A1032
+ @A1033
+ @A1034
+ @A1035
+ @A1036
+ @A1037
+ @A1038
+ @A1039
+ @A1040
+ @A1041
+ @A1042
+ @A1043
+ @A1044
+ @A1045
+ @A1046
+ @A1047
+ @A1048
+ @A1049
+ @A1050
+ @A1051
+ @A1052
+ @A1053
+ @A1054
+ @A1055
+ @A1056
+ @A1057
+ @A1058
+ @A1059
+ @A1060
+ @A1061
+ @A1062
+ @A1063
+ @A1064
+ @A1065
+ @A1066
+ @A1067
+ @A1068
+ @A1069
+ @A1070
+ @A1071
+ @A1072
+ @A1073
+ @A1074
+ @A1075
+ @A1076
+ @A1077
+ @A1078
+ @A1079
+ @A1080
+ @A1081
+ @A1082
+ @A1083
+ @A1084
+ @A1085
+ @A1086
+ @A1087
+ @A1088
+ @A1089
+ @A1090
+ @A1091
+ @A1092
+ @A1093
+ @A1094
+ @A1095
+ @A1096
+ @A1097
+ @A1098
+ @A1099
+ @A1100
+ @A1101
+ @A1102
+ @A1103
+ @A1104
+ @A1105
+ @A1106
+ @A1107
+ @A1108
+ @A1109
+ @A1110
+ @A1111
+ @A1112
+ @A1113
+ @A1114
+ @A1115
+ @A1116
+ @A1117
+ @A1118
+ @A1119
+ @A1120
+ @A1121
+ @A1122
+ @A1123
+ @A1124
+ @A1125
+ @A1126
+ @A1127
+ @A1128
+ @A1129
+ @A1130
+ @A1131
+ @A1132
+ @A1133
+ @A1134
+ @A1135
+ @A1136
+ @A1137
+ @A1138
+ @A1139
+ @A1140
+ @A1141
+ @A1142
+ @A1143
+ @A1144
+ @A1145
+ @A1146
+ @A1147
+ @A1148
+ @A1149
+ @A1150
+ @A1151
+ @A1152
+ @A1153
+ @A1154
+ @A1155
+ @A1156
+ @A1157
+ @A1158
+ @A1159
+ @A1160
+ @A1161
+ @A1162
+ @A1163
+ @A1164
+ @A1165
+ @A1166
+ @A1167
+ @A1168
+ @A1169
+ @A1170
+ @A1171
+ @A1172
+ @A1173
+ @A1174
+ @A1175
+ @A1176
+ @A1177
+ @A1178
+ @A1179
+ @A1180
+ @A1181
+ @A1182
+ @A1183
+ @A1184
+ @A1185
+ @A1186
+ @A1187
+ @A1188
+ @A1189
+ @A1190
+ @A1191
+ @A1192
+ @A1193
+ @A1194
+ @A1195
+ @A1196
+ @A1197
+ @A1198
+ @A1199
+ @A1200
+ @A1201
+ @A1202
+ @A1203
+ @A1204
+ @A1205
+ @A1206
+ @A1207
+ @A1208
+ @A1209
+ @A1210
+ @A1211
+ @A1212
+ @A1213
+ @A1214
+ @A1215
+ @A1216
+ @A1217
+ @A1218
+ @A1219
+ @A1220
+ @A1221
+ @A1222
+ @A1223
+ @A1224
+ @A1225
+ @A1226
+ @A1227
+ @A1228
+ @A1229
+ @A1230
+ @A1231
+ @A1232
+ @A1233
+ @A1234
+ @A1235
+ @A1236
+ @A1237
+ @A1238
+ @A1239
+ @A1240
+ @A1241
+ @A1242
+ @A1243
+ @A1244
+ @A1245
+ @A1246
+ @A1247
+ @A1248
+ @A1249
+ @A1250
+ @A1251
+ @A1252
+ @A1253
+ @A1254
+ @A1255
+ @A1256
+ @A1257
+ @A1258
+ @A1259
+ @A1260
+ @A1261
+ @A1262
+ @A1263
+ @A1264
+ @A1265
+ @A1266
+ @A1267
+ @A1268
+ @A1269
+ @A1270
+ @A1271
+ @A1272
+ @A1273
+ @A1274
+ @A1275
+ @A1276
+ @A1277
+ @A1278
+ @A1279
+ @A1280
+ @A1281
+ @A1282
+ @A1283
+ @A1284
+ @A1285
+ @A1286
+ @A1287
+ @A1288
+ @A1289
+ @A1290
+ @A1291
+ @A1292
+ @A1293
+ @A1294
+ @A1295
+ @A1296
+ @A1297
+ @A1298
+ @A1299
+ @A1300
+ @A1301
+ @A1302
+ @A1303
+ @A1304
+ @A1305
+ @A1306
+ @A1307
+ @A1308
+ @A1309
+ @A1310
+ @A1311
+ @A1312
+ @A1313
+ @A1314
+ @A1315
+ @A1316
+ @A1317
+ @A1318
+ @A1319
+ @A1320
+ @A1321
+ @A1322
+ @A1323
+ @A1324
+ @A1325
+ @A1326
+ @A1327
+ @A1328
+ @A1329
+ @A1330
+ @A1331
+ @A1332
+ @A1333
+ @A1334
+ @A1335
+ @A1336
+ @A1337
+ @A1338
+ @A1339
+ @A1340
+ @A1341
+ @A1342
+ @A1343
+ @A1344
+ @A1345
+ @A1346
+ @A1347
+ @A1348
+ @A1349
+ @A1350
+ @A1351
+ @A1352
+ @A1353
+ @A1354
+ @A1355
+ @A1356
+ @A1357
+ @A1358
+ @A1359
+ @A1360
+ @A1361
+ @A1362
+ @A1363
+ @A1364
+ @A1365
+ @A1366
+ @A1367
+ @A1368
+ @A1369
+ @A1370
+ @A1371
+ @A1372
+ @A1373
+ @A1374
+ @A1375
+ @A1376
+ @A1377
+ @A1378
+ @A1379
+ @A1380
+ @A1381
+ @A1382
+ @A1383
+ @A1384
+ @A1385
+ @A1386
+ @A1387
+ @A1388
+ @A1389
+ @A1390
+ @A1391
+ @A1392
+ @A1393
+ @A1394
+ @A1395
+ @A1396
+ @A1397
+ @A1398
+ @A1399
+ @A1400
+ @A1401
+ @A1402
+ @A1403
+ @A1404
+ @A1405
+ @A1406
+ @A1407
+ @A1408
+ @A1409
+ @A1410
+ @A1411
+ @A1412
+ @A1413
+ @A1414
+ @A1415
+ @A1416
+ @A1417
+ @A1418
+ @A1419
+ @A1420
+ @A1421
+ @A1422
+ @A1423
+ @A1424
+ @A1425
+ @A1426
+ @A1427
+ @A1428
+ @A1429
+ @A1430
+ @A1431
+ @A1432
+ @A1433
+ @A1434
+ @A1435
+ @A1436
+ @A1437
+ @A1438
+ @A1439
+ @A1440
+ @A1441
+ @A1442
+ @A1443
+ @A1444
+ @A1445
+ @A1446
+ @A1447
+ @A1448
+ @A1449
+ @A1450
+ @A1451
+ @A1452
+ @A1453
+ @A1454
+ @A1455
+ @A1456
+ @A1457
+ @A1458
+ @A1459
+ @A1460
+ @A1461
+ @A1462
+ @A1463
+ @A1464
+ @A1465
+ @A1466
+ @A1467
+ @A1468
+ @A1469
+ @A1470
+ @A1471
+ @A1472
+ @A1473
+ @A1474
+ @A1475
+ @A1476
+ @A1477
+ @A1478
+ @A1479
+ @A1480
+ @A1481
+ @A1482
+ @A1483
+ @A1484
+ @A1485
+ @A1486
+ @A1487
+ @A1488
+ @A1489
+ @A1490
+ @A1491
+ @A1492
+ @A1493
+ @A1494
+ @A1495
+ @A1496
+ @A1497
+ @A1498
+ @A1499
+ @A1500
+ @A1501
+ @A1502
+ @A1503
+ @A1504
+ @A1505
+ @A1506
+ @A1507
+ @A1508
+ @A1509
+ @A1510
+ @A1511
+ @A1512
+ @A1513
+ @A1514
+ @A1515
+ @A1516
+ @A1517
+ @A1518
+ @A1519
+ @A1520
+ @A1521
+ @A1522
+ @A1523
+ @A1524
+ @A1525
+ @A1526
+ @A1527
+ @A1528
+ @A1529
+ @A1530
+ @A1531
+ @A1532
+ @A1533
+ @A1534
+ @A1535
+ @A1536
+ @A1537
+ @A1538
+ @A1539
+ @A1540
+ @A1541
+ @A1542
+ @A1543
+ @A1544
+ @A1545
+ @A1546
+ @A1547
+ @A1548
+ @A1549
+ @A1550
+ @A1551
+ @A1552
+ @A1553
+ @A1554
+ @A1555
+ @A1556
+ @A1557
+ @A1558
+ @A1559
+ @A1560
+ @A1561
+ @A1562
+ @A1563
+ @A1564
+ @A1565
+ @A1566
+ @A1567
+ @A1568
+ @A1569
+ @A1570
+ @A1571
+ @A1572
+ @A1573
+ @A1574
+ @A1575
+ @A1576
+ @A1577
+ @A1578
+ @A1579
+ @A1580
+ @A1581
+ @A1582
+ @A1583
+ @A1584
+ @A1585
+ @A1586
+ @A1587
+ @A1588
+ @A1589
+ @A1590
+ @A1591
+ @A1592
+ @A1593
+ @A1594
+ @A1595
+ @A1596
+ @A1597
+ @A1598
+ @A1599
+ @A1600
+ @A1601
+ @A1602
+ @A1603
+ @A1604
+ @A1605
+ @A1606
+ @A1607
+ @A1608
+ @A1609
+ @A1610
+ @A1611
+ @A1612
+ @A1613
+ @A1614
+ @A1615
+ @A1616
+ @A1617
+ @A1618
+ @A1619
+ @A1620
+ @A1621
+ @A1622
+ @A1623
+ @A1624
+ @A1625
+ @A1626
+ @A1627
+ @A1628
+ @A1629
+ @A1630
+ @A1631
+ @A1632
+ @A1633
+ @A1634
+ @A1635
+ @A1636
+ @A1637
+ @A1638
+ @A1639
+ @A1640
+ @A1641
+ @A1642
+ @A1643
+ @A1644
+ @A1645
+ @A1646
+ @A1647
+ @A1648
+ @A1649
+ @A1650
+ @A1651
+ @A1652
+ @A1653
+ @A1654
+ @A1655
+ @A1656
+ @A1657
+ @A1658
+ @A1659
+ @A1660
+ @A1661
+ @A1662
+ @A1663
+ @A1664
+ @A1665
+ @A1666
+ @A1667
+ @A1668
+ @A1669
+ @A1670
+ @A1671
+ @A1672
+ @A1673
+ @A1674
+ @A1675
+ @A1676
+ @A1677
+ @A1678
+ @A1679
+ @A1680
+ @A1681
+ @A1682
+ @A1683
+ @A1684
+ @A1685
+ @A1686
+ @A1687
+ @A1688
+ @A1689
+ @A1690
+ @A1691
+ @A1692
+ @A1693
+ @A1694
+ @A1695
+ @A1696
+ @A1697
+ @A1698
+ @A1699
+ @A1700
+ @A1701
+ @A1702
+ @A1703
+ @A1704
+ @A1705
+ @A1706
+ @A1707
+ @A1708
+ @A1709
+ @A1710
+ @A1711
+ @A1712
+ @A1713
+ @A1714
+ @A1715
+ @A1716
+ @A1717
+ @A1718
+ @A1719
+ @A1720
+ @A1721
+ @A1722
+ @A1723
+ @A1724
+ @A1725
+ @A1726
+ @A1727
+ @A1728
+ @A1729
+ @A1730
+ @A1731
+ @A1732
+ @A1733
+ @A1734
+ @A1735
+ @A1736
+ @A1737
+ @A1738
+ @A1739
+ @A1740
+ @A1741
+ @A1742
+ @A1743
+ @A1744
+ @A1745
+ @A1746
+ @A1747
+ @A1748
+ @A1749
+ @A1750
+ @A1751
+ @A1752
+ @A1753
+ @A1754
+ @A1755
+ @A1756
+ @A1757
+ @A1758
+ @A1759
+ @A1760
+ @A1761
+ @A1762
+ @A1763
+ @A1764
+ @A1765
+ @A1766
+ @A1767
+ @A1768
+ @A1769
+ @A1770
+ @A1771
+ @A1772
+ @A1773
+ @A1774
+ @A1775
+ @A1776
+ @A1777
+ @A1778
+ @A1779
+ @A1780
+ @A1781
+ @A1782
+ @A1783
+ @A1784
+ @A1785
+ @A1786
+ @A1787
+ @A1788
+ @A1789
+ @A1790
+ @A1791
+ @A1792
+ @A1793
+ @A1794
+ @A1795
+ @A1796
+ @A1797
+ @A1798
+ @A1799
+ @A1800
+ @A1801
+ @A1802
+ @A1803
+ @A1804
+ @A1805
+ @A1806
+ @A1807
+ @A1808
+ @A1809
+ @A1810
+ @A1811
+ @A1812
+ @A1813
+ @A1814
+ @A1815
+ @A1816
+ @A1817
+ @A1818
+ @A1819
+ @A1820
+ @A1821
+ @A1822
+ @A1823
+ @A1824
+ @A1825
+ @A1826
+ @A1827
+ @A1828
+ @A1829
+ @A1830
+ @A1831
+ @A1832
+ @A1833
+ @A1834
+ @A1835
+ @A1836
+ @A1837
+ @A1838
+ @A1839
+ @A1840
+ @A1841
+ @A1842
+ @A1843
+ @A1844
+ @A1845
+ @A1846
+ @A1847
+ @A1848
+ @A1849
+ @A1850
+ @A1851
+ @A1852
+ @A1853
+ @A1854
+ @A1855
+ @A1856
+ @A1857
+ @A1858
+ @A1859
+ @A1860
+ @A1861
+ @A1862
+ @A1863
+ @A1864
+ @A1865
+ @A1866
+ @A1867
+ @A1868
+ @A1869
+ @A1870
+ @A1871
+ @A1872
+ @A1873
+ @A1874
+ @A1875
+ @A1876
+ @A1877
+ @A1878
+ @A1879
+ @A1880
+ @A1881
+ @A1882
+ @A1883
+ @A1884
+ @A1885
+ @A1886
+ @A1887
+ @A1888
+ @A1889
+ @A1890
+ @A1891
+ @A1892
+ @A1893
+ @A1894
+ @A1895
+ @A1896
+ @A1897
+ @A1898
+ @A1899
+ @A1900
+ @A1901
+ @A1902
+ @A1903
+ @A1904
+ @A1905
+ @A1906
+ @A1907
+ @A1908
+ @A1909
+ @A1910
+ @A1911
+ @A1912
+ @A1913
+ @A1914
+ @A1915
+ @A1916
+ @A1917
+ @A1918
+ @A1919
+ @A1920
+ @A1921
+ @A1922
+ @A1923
+ @A1924
+ @A1925
+ @A1926
+ @A1927
+ @A1928
+ @A1929
+ @A1930
+ @A1931
+ @A1932
+ @A1933
+ @A1934
+ @A1935
+ @A1936
+ @A1937
+ @A1938
+ @A1939
+ @A1940
+ @A1941
+ @A1942
+ @A1943
+ @A1944
+ @A1945
+ @A1946
+ @A1947
+ @A1948
+ @A1949
+ @A1950
+ @A1951
+ @A1952
+ @A1953
+ @A1954
+ @A1955
+ @A1956
+ @A1957
+ @A1958
+ @A1959
+ @A1960
+ @A1961
+ @A1962
+ @A1963
+ @A1964
+ @A1965
+ @A1966
+ @A1967
+ @A1968
+ @A1969
+ @A1970
+ @A1971
+ @A1972
+ @A1973
+ @A1974
+ @A1975
+ @A1976
+ @A1977
+ @A1978
+ @A1979
+ @A1980
+ @A1981
+ @A1982
+ @A1983
+ @A1984
+ @A1985
+ @A1986
+ @A1987
+ @A1988
+ @A1989
+ @A1990
+ @A1991
+ @A1992
+ @A1993
+ @A1994
+ @A1995
+ @A1996
+ @A1997
+ @A1998
+ @A1999
+ @A2000
+ @A2001
+ @A2002
+ @A2003
+ @A2004
+ @A2005
+ @A2006
+ @A2007
+ @A2008
+ @A2009
+ @A2010
+ @A2011
+ @A2012
+ @A2013
+ @A2014
+ @A2015
+ @A2016
+ @A2017
+ @A2018
+ @A2019
+ @A2020
+ @A2021
+ @A2022
+ @A2023
+ @A2024
+ @A2025
+ @A2026
+ @A2027
+ @A2028
+ @A2029
+ @A2030
+ @A2031
+ @A2032
+ @A2033
+ @A2034
+ @A2035
+ @A2036
+ @A2037
+ @A2038
+ @A2039
+ @A2040
+ @A2041
+ @A2042
+ @A2043
+ @A2044
+ @A2045
+ @A2046
+ @A2047
+ @A2048
+ @A2049
+ @A2050
+ @A2051
+ @A2052
+ @A2053
+ @A2054
+ @A2055
+ @A2056
+ @A2057
+ @A2058
+ @A2059
+ @A2060
+ @A2061
+ @A2062
+ @A2063
+ @A2064
+ @A2065
+ @A2066
+ @A2067
+ @A2068
+ @A2069
+ @A2070
+ @A2071
+ @A2072
+ @A2073
+ @A2074
+ @A2075
+ @A2076
+ @A2077
+ @A2078
+ @A2079
+ @A2080
+ @A2081
+ @A2082
+ @A2083
+ @A2084
+ @A2085
+ @A2086
+ @A2087
+ @A2088
+ @A2089
+ @A2090
+ @A2091
+ @A2092
+ @A2093
+ @A2094
+ @A2095
+ @A2096
+ @A2097
+ @A2098
+ @A2099
+ @A2100
+ @A2101
+ @A2102
+ @A2103
+ @A2104
+ @A2105
+ @A2106
+ @A2107
+ @A2108
+ @A2109
+ @A2110
+ @A2111
+ @A2112
+ @A2113
+ @A2114
+ @A2115
+ @A2116
+ @A2117
+ @A2118
+ @A2119
+ @A2120
+ @A2121
+ @A2122
+ @A2123
+ @A2124
+ @A2125
+ @A2126
+ @A2127
+ @A2128
+ @A2129
+ @A2130
+ @A2131
+ @A2132
+ @A2133
+ @A2134
+ @A2135
+ @A2136
+ @A2137
+ @A2138
+ @A2139
+ @A2140
+ @A2141
+ @A2142
+ @A2143
+ @A2144
+ @A2145
+ @A2146
+ @A2147
+ @A2148
+ @A2149
+ @A2150
+ @A2151
+ @A2152
+ @A2153
+ @A2154
+ @A2155
+ @A2156
+ @A2157
+ @A2158
+ @A2159
+ @A2160
+ @A2161
+ @A2162
+ @A2163
+ @A2164
+ @A2165
+ @A2166
+ @A2167
+ @A2168
+ @A2169
+ @A2170
+ @A2171
+ @A2172
+ @A2173
+ @A2174
+ @A2175
+ @A2176
+ @A2177
+ @A2178
+ @A2179
+ @A2180
+ @A2181
+ @A2182
+ @A2183
+ @A2184
+ @A2185
+ @A2186
+ @A2187
+ @A2188
+ @A2189
+ @A2190
+ @A2191
+ @A2192
+ @A2193
+ @A2194
+ @A2195
+ @A2196
+ @A2197
+ @A2198
+ @A2199
+ @A2200
+ @A2201
+ @A2202
+ @A2203
+ @A2204
+ @A2205
+ @A2206
+ @A2207
+ @A2208
+ @A2209
+ @A2210
+ @A2211
+ @A2212
+ @A2213
+ @A2214
+ @A2215
+ @A2216
+ @A2217
+ @A2218
+ @A2219
+ @A2220
+ @A2221
+ @A2222
+ @A2223
+ @A2224
+ @A2225
+ @A2226
+ @A2227
+ @A2228
+ @A2229
+ @A2230
+ @A2231
+ @A2232
+ @A2233
+ @A2234
+ @A2235
+ @A2236
+ @A2237
+ @A2238
+ @A2239
+ @A2240
+ @A2241
+ @A2242
+ @A2243
+ @A2244
+ @A2245
+ @A2246
+ @A2247
+ @A2248
+ @A2249
+ @A2250
+ @A2251
+ @A2252
+ @A2253
+ @A2254
+ @A2255
+ @A2256
+ @A2257
+ @A2258
+ @A2259
+ @A2260
+ @A2261
+ @A2262
+ @A2263
+ @A2264
+ @A2265
+ @A2266
+ @A2267
+ @A2268
+ @A2269
+ @A2270
+ @A2271
+ @A2272
+ @A2273
+ @A2274
+ @A2275
+ @A2276
+ @A2277
+ @A2278
+ @A2279
+ @A2280
+ @A2281
+ @A2282
+ @A2283
+ @A2284
+ @A2285
+ @A2286
+ @A2287
+ @A2288
+ @A2289
+ @A2290
+ @A2291
+ @A2292
+ @A2293
+ @A2294
+ @A2295
+ @A2296
+ @A2297
+ @A2298
+ @A2299
+ @A2300
+ @A2301
+ @A2302
+ @A2303
+ @A2304
+ @A2305
+ @A2306
+ @A2307
+ @A2308
+ @A2309
+ @A2310
+ @A2311
+ @A2312
+ @A2313
+ @A2314
+ @A2315
+ @A2316
+ @A2317
+ @A2318
+ @A2319
+ @A2320
+ @A2321
+ @A2322
+ @A2323
+ @A2324
+ @A2325
+ @A2326
+ @A2327
+ @A2328
+ @A2329
+ @A2330
+ @A2331
+ @A2332
+ @A2333
+ @A2334
+ @A2335
+ @A2336
+ @A2337
+ @A2338
+ @A2339
+ @A2340
+ @A2341
+ @A2342
+ @A2343
+ @A2344
+ @A2345
+ @A2346
+ @A2347
+ @A2348
+ @A2349
+ @A2350
+ @A2351
+ @A2352
+ @A2353
+ @A2354
+ @A2355
+ @A2356
+ @A2357
+ @A2358
+ @A2359
+ @A2360
+ @A2361
+ @A2362
+ @A2363
+ @A2364
+ @A2365
+ @A2366
+ @A2367
+ @A2368
+ @A2369
+ @A2370
+ @A2371
+ @A2372
+ @A2373
+ @A2374
+ @A2375
+ @A2376
+ @A2377
+ @A2378
+ @A2379
+ @A2380
+ @A2381
+ @A2382
+ @A2383
+ @A2384
+ @A2385
+ @A2386
+ @A2387
+ @A2388
+ @A2389
+ @A2390
+ @A2391
+ @A2392
+ @A2393
+ @A2394
+ @A2395
+ @A2396
+ @A2397
+ @A2398
+ @A2399
+ @A2400
+ @A2401
+ @A2402
+ @A2403
+ @A2404
+ @A2405
+ @A2406
+ @A2407
+ @A2408
+ @A2409
+ @A2410
+ @A2411
+ @A2412
+ @A2413
+ @A2414
+ @A2415
+ @A2416
+ @A2417
+ @A2418
+ @A2419
+ @A2420
+ @A2421
+ @A2422
+ @A2423
+ @A2424
+ @A2425
+ @A2426
+ @A2427
+ @A2428
+ @A2429
+ @A2430
+ @A2431
+ @A2432
+ @A2433
+ @A2434
+ @A2435
+ @A2436
+ @A2437
+ @A2438
+ @A2439
+ @A2440
+ @A2441
+ @A2442
+ @A2443
+ @A2444
+ @A2445
+ @A2446
+ @A2447
+ @A2448
+ @A2449
+ @A2450
+ @A2451
+ @A2452
+ @A2453
+ @A2454
+ @A2455
+ @A2456
+ @A2457
+ @A2458
+ @A2459
+ @A2460
+ @A2461
+ @A2462
+ @A2463
+ @A2464
+ @A2465
+ @A2466
+ @A2467
+ @A2468
+ @A2469
+ @A2470
+ @A2471
+ @A2472
+ @A2473
+ @A2474
+ @A2475
+ @A2476
+ @A2477
+ @A2478
+ @A2479
+ @A2480
+ @A2481
+ @A2482
+ @A2483
+ @A2484
+ @A2485
+ @A2486
+ @A2487
+ @A2488
+ @A2489
+ @A2490
+ @A2491
+ @A2492
+ @A2493
+ @A2494
+ @A2495
+ @A2496
+ @A2497
+ @A2498
+ @A2499
+ @A2500
+ @A2501
+ @A2502
+ @A2503
+ @A2504
+ @A2505
+ @A2506
+ @A2507
+ @A2508
+ @A2509
+ @A2510
+ @A2511
+ @A2512
+ @A2513
+ @A2514
+ @A2515
+ @A2516
+ @A2517
+ @A2518
+ @A2519
+ @A2520
+ @A2521
+ @A2522
+ @A2523
+ @A2524
+ @A2525
+ @A2526
+ @A2527
+ @A2528
+ @A2529
+ @A2530
+ @A2531
+ @A2532
+ @A2533
+ @A2534
+ @A2535
+ @A2536
+ @A2537
+ @A2538
+ @A2539
+ @A2540
+ @A2541
+ @A2542
+ @A2543
+ @A2544
+ @A2545
+ @A2546
+ @A2547
+ @A2548
+ @A2549
+ @A2550
+ @A2551
+ @A2552
+ @A2553
+ @A2554
+ @A2555
+ @A2556
+ @A2557
+ @A2558
+ @A2559
+ @A2560
+ @A2561
+ @A2562
+ @A2563
+ @A2564
+ @A2565
+ @A2566
+ @A2567
+ @A2568
+ @A2569
+ @A2570
+ @A2571
+ @A2572
+ @A2573
+ @A2574
+ @A2575
+ @A2576
+ @A2577
+ @A2578
+ @A2579
+ @A2580
+ @A2581
+ @A2582
+ @A2583
+ @A2584
+ @A2585
+ @A2586
+ @A2587
+ @A2588
+ @A2589
+ @A2590
+ @A2591
+ @A2592
+ @A2593
+ @A2594
+ @A2595
+ @A2596
+ @A2597
+ @A2598
+ @A2599
+ @A2600
+ @A2601
+ @A2602
+ @A2603
+ @A2604
+ @A2605
+ @A2606
+ @A2607
+ @A2608
+ @A2609
+ @A2610
+ @A2611
+ @A2612
+ @A2613
+ @A2614
+ @A2615
+ @A2616
+ @A2617
+ @A2618
+ @A2619
+ @A2620
+ @A2621
+ @A2622
+ @A2623
+ @A2624
+ @A2625
+ @A2626
+ @A2627
+ @A2628
+ @A2629
+ @A2630
+ @A2631
+ @A2632
+ @A2633
+ @A2634
+ @A2635
+ @A2636
+ @A2637
+ @A2638
+ @A2639
+ @A2640
+ @A2641
+ @A2642
+ @A2643
+ @A2644
+ @A2645
+ @A2646
+ @A2647
+ @A2648
+ @A2649
+ @A2650
+ @A2651
+ @A2652
+ @A2653
+ @A2654
+ @A2655
+ @A2656
+ @A2657
+ @A2658
+ @A2659
+ @A2660
+ @A2661
+ @A2662
+ @A2663
+ @A2664
+ @A2665
+ @A2666
+ @A2667
+ @A2668
+ @A2669
+ @A2670
+ @A2671
+ @A2672
+ @A2673
+ @A2674
+ @A2675
+ @A2676
+ @A2677
+ @A2678
+ @A2679
+ @A2680
+ @A2681
+ @A2682
+ @A2683
+ @A2684
+ @A2685
+ @A2686
+ @A2687
+ @A2688
+ @A2689
+ @A2690
+ @A2691
+ @A2692
+ @A2693
+ @A2694
+ @A2695
+ @A2696
+ @A2697
+ @A2698
+ @A2699
+ @A2700
+ @A2701
+ @A2702
+ @A2703
+ @A2704
+ @A2705
+ @A2706
+ @A2707
+ @A2708
+ @A2709
+ @A2710
+ @A2711
+ @A2712
+ @A2713
+ @A2714
+ @A2715
+ @A2716
+ @A2717
+ @A2718
+ @A2719
+ @A2720
+ @A2721
+ @A2722
+ @A2723
+ @A2724
+ @A2725
+ @A2726
+ @A2727
+ @A2728
+ @A2729
+ @A2730
+ @A2731
+ @A2732
+ @A2733
+ @A2734
+ @A2735
+ @A2736
+ @A2737
+ @A2738
+ @A2739
+ @A2740
+ @A2741
+ @A2742
+ @A2743
+ @A2744
+ @A2745
+ @A2746
+ @A2747
+ @A2748
+ @A2749
+ @A2750
+ @A2751
+ @A2752
+ @A2753
+ @A2754
+ @A2755
+ @A2756
+ @A2757
+ @A2758
+ @A2759
+ @A2760
+ @A2761
+ @A2762
+ @A2763
+ @A2764
+ @A2765
+ @A2766
+ @A2767
+ @A2768
+ @A2769
+ @A2770
+ @A2771
+ @A2772
+ @A2773
+ @A2774
+ @A2775
+ @A2776
+ @A2777
+ @A2778
+ @A2779
+ @A2780
+ @A2781
+ @A2782
+ @A2783
+ @A2784
+ @A2785
+ @A2786
+ @A2787
+ @A2788
+ @A2789
+ @A2790
+ @A2791
+ @A2792
+ @A2793
+ @A2794
+ @A2795
+ @A2796
+ @A2797
+ @A2798
+ @A2799
+ @A2800
+ @A2801
+ @A2802
+ @A2803
+ @A2804
+ @A2805
+ @A2806
+ @A2807
+ @A2808
+ @A2809
+ @A2810
+ @A2811
+ @A2812
+ @A2813
+ @A2814
+ @A2815
+ @A2816
+ @A2817
+ @A2818
+ @A2819
+ @A2820
+ @A2821
+ @A2822
+ @A2823
+ @A2824
+ @A2825
+ @A2826
+ @A2827
+ @A2828
+ @A2829
+ @A2830
+ @A2831
+ @A2832
+ @A2833
+ @A2834
+ @A2835
+ @A2836
+ @A2837
+ @A2838
+ @A2839
+ @A2840
+ @A2841
+ @A2842
+ @A2843
+ @A2844
+ @A2845
+ @A2846
+ @A2847
+ @A2848
+ @A2849
+ @A2850
+ @A2851
+ @A2852
+ @A2853
+ @A2854
+ @A2855
+ @A2856
+ @A2857
+ @A2858
+ @A2859
+ @A2860
+ @A2861
+ @A2862
+ @A2863
+ @A2864
+ @A2865
+ @A2866
+ @A2867
+ @A2868
+ @A2869
+ @A2870
+ @A2871
+ @A2872
+ @A2873
+ @A2874
+ @A2875
+ @A2876
+ @A2877
+ @A2878
+ @A2879
+ @A2880
+ @A2881
+ @A2882
+ @A2883
+ @A2884
+ @A2885
+ @A2886
+ @A2887
+ @A2888
+ @A2889
+ @A2890
+ @A2891
+ @A2892
+ @A2893
+ @A2894
+ @A2895
+ @A2896
+ @A2897
+ @A2898
+ @A2899
+ @A2900
+ @A2901
+ @A2902
+ @A2903
+ @A2904
+ @A2905
+ @A2906
+ @A2907
+ @A2908
+ @A2909
+ @A2910
+ @A2911
+ @A2912
+ @A2913
+ @A2914
+ @A2915
+ @A2916
+ @A2917
+ @A2918
+ @A2919
+ @A2920
+ @A2921
+ @A2922
+ @A2923
+ @A2924
+ @A2925
+ @A2926
+ @A2927
+ @A2928
+ @A2929
+ @A2930
+ @A2931
+ @A2932
+ @A2933
+ @A2934
+ @A2935
+ @A2936
+ @A2937
+ @A2938
+ @A2939
+ @A2940
+ @A2941
+ @A2942
+ @A2943
+ @A2944
+ @A2945
+ @A2946
+ @A2947
+ @A2948
+ @A2949
+ @A2950
+ @A2951
+ @A2952
+ @A2953
+ @A2954
+ @A2955
+ @A2956
+ @A2957
+ @A2958
+ @A2959
+ @A2960
+ @A2961
+ @A2962
+ @A2963
+ @A2964
+ @A2965
+ @A2966
+ @A2967
+ @A2968
+ @A2969
+ @A2970
+ @A2971
+ @A2972
+ @A2973
+ @A2974
+ @A2975
+ @A2976
+ @A2977
+ @A2978
+ @A2979
+ @A2980
+ @A2981
+ @A2982
+ @A2983
+ @A2984
+ @A2985
+ @A2986
+ @A2987
+ @A2988
+ @A2989
+ @A2990
+ @A2991
+ @A2992
+ @A2993
+ @A2994
+ @A2995
+ @A2996
+ @A2997
+ @A2998
+ @A2999
+ class A {}
+
+ @Retention(RetentionPolicy.RUNTIME) @interface B0 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B3 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B4 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B5 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B6 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B7 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B8 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B9 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B10 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B11 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B12 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B13 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B14 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B15 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B16 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B17 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B18 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B19 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B20 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B21 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B22 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B23 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B24 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B25 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B26 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B27 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B28 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B29 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B30 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B31 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B32 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B33 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B34 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B35 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B36 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B37 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B38 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B39 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B40 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B41 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B42 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B43 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B44 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B45 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B46 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B47 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B48 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B49 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B50 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B51 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B52 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B53 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B54 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B55 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B56 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B57 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B58 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B59 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B60 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B61 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B62 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B63 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B64 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B65 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B66 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B67 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B68 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B69 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B70 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B71 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B72 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B73 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B74 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B75 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B76 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B77 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B78 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B79 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B80 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B81 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B82 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B83 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B84 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B85 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B86 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B87 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B88 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B89 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B90 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B91 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B92 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B93 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B94 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B95 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B96 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B97 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B98 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B99 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B999 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1000 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1001 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1002 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1003 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1004 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1005 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1006 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1007 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1008 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1009 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1010 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1011 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1012 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1013 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1014 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1015 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1016 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1017 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1018 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1019 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1020 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1021 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1022 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1023 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1024 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1025 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1026 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1027 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1028 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1029 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1030 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1031 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1032 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1033 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1034 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1035 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1036 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1037 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1038 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1039 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1040 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1041 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1042 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1043 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1044 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1045 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1046 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1047 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1048 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1049 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1050 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1051 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1052 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1053 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1054 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1055 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1056 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1057 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1058 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1059 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1060 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1061 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1062 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1063 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1064 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1065 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1066 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1067 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1068 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1069 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1070 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1071 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1072 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1073 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1074 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1075 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1076 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1077 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1078 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1079 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1080 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1081 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1082 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1083 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1084 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1085 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1086 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1087 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1088 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1089 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1090 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1091 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1092 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1093 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1094 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1095 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1096 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1097 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1098 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1099 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B1999 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2000 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2001 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2002 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2003 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2004 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2005 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2006 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2007 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2008 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2009 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2010 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2011 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2012 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2013 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2014 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2015 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2016 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2017 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2018 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2019 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2020 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2021 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2022 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2023 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2024 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2025 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2026 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2027 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2028 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2029 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2030 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2031 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2032 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2033 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2034 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2035 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2036 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2037 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2038 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2039 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2040 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2041 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2042 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2043 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2044 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2045 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2046 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2047 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2048 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2049 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2050 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2051 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2052 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2053 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2054 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2055 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2056 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2057 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2058 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2059 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2060 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2061 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2062 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2063 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2064 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2065 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2066 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2067 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2068 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2069 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2070 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2071 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2072 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2073 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2074 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2075 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2076 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2077 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2078 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2079 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2080 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2081 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2082 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2083 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2084 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2085 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2086 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2087 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2088 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2089 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2090 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2091 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2092 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2093 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2094 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2095 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2096 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2097 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2098 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2099 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2100 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2101 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2102 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2103 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2104 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2105 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2106 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2107 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2108 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2109 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2110 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2111 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2112 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2113 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2114 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2115 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2116 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2117 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2118 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2119 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2120 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2121 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2122 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2123 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2124 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2125 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2126 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2127 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2128 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2129 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2130 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2131 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2132 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2133 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2134 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2135 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2136 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2137 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2138 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2139 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2140 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2141 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2142 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2143 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2144 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2145 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2146 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2147 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2148 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2149 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2150 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2151 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2152 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2153 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2154 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2155 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2156 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2157 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2158 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2159 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2160 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2161 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2162 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2163 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2164 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2165 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2166 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2167 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2168 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2169 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2170 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2171 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2172 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2173 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2174 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2175 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2176 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2177 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2178 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2179 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2180 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2181 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2182 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2183 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2184 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2185 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2186 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2187 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2188 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2189 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2190 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2191 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2192 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2193 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2194 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2195 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2196 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2197 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2198 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2199 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2200 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2201 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2202 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2203 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2204 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2205 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2206 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2207 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2208 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2209 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2210 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2211 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2212 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2213 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2214 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2215 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2216 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2217 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2218 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2219 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2220 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2221 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2222 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2223 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2224 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2225 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2226 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2227 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2228 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2229 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2230 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2231 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2232 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2233 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2234 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2235 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2236 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2237 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2238 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2239 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2240 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2241 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2242 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2243 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2244 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2245 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2246 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2247 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2248 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2249 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2250 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2251 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2252 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2253 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2254 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2255 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2256 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2257 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2258 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2259 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2260 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2261 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2262 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2263 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2264 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2265 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2266 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2267 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2268 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2269 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2270 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2271 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2272 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2273 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2274 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2275 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2276 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2277 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2278 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2279 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2280 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2281 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2282 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2283 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2284 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2285 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2286 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2287 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2288 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2289 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2290 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2291 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2292 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2293 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2294 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2295 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2296 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2297 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2298 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2299 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2300 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2301 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2302 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2303 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2304 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2305 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2306 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2307 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2308 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2309 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2310 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2311 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2312 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2313 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2314 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2315 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2316 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2317 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2318 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2319 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2320 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2321 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2322 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2323 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2324 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2325 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2326 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2327 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2328 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2329 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2330 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2331 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2332 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2333 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2334 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2335 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2336 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2337 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2338 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2339 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2340 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2341 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2342 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2343 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2344 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2345 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2346 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2347 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2348 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2349 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2350 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2351 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2352 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2353 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2354 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2355 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2356 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2357 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2358 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2359 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2360 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2361 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2362 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2363 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2364 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2365 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2366 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2367 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2368 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2369 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2370 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2371 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2372 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2373 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2374 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2375 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2376 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2377 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2378 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2379 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2380 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2381 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2382 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2383 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2384 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2385 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2386 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2387 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2388 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2389 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2390 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2391 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2392 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2393 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2394 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2395 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2396 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2397 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2398 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2399 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2400 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2401 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2402 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2403 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2404 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2405 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2406 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2407 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2408 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2409 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2410 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2411 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2412 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2413 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2414 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2415 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2416 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2417 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2418 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2419 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2420 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2421 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2422 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2423 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2424 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2425 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2426 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2427 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2428 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2429 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2430 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2431 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2432 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2433 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2434 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2435 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2436 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2437 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2438 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2439 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2440 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2441 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2442 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2443 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2444 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2445 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2446 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2447 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2448 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2449 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2450 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2451 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2452 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2453 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2454 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2455 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2456 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2457 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2458 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2459 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2460 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2461 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2462 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2463 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2464 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2465 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2466 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2467 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2468 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2469 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2470 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2471 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2472 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2473 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2474 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2475 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2476 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2477 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2478 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2479 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2480 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2481 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2482 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2483 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2484 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2485 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2486 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2487 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2488 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2489 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2490 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2491 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2492 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2493 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2494 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2495 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2496 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2497 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2498 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2499 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2500 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2501 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2502 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2503 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2504 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2505 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2506 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2507 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2508 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2509 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2510 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2511 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2512 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2513 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2514 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2515 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2516 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2517 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2518 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2519 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2520 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2521 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2522 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2523 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2524 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2525 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2526 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2527 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2528 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2529 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2530 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2531 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2532 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2533 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2534 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2535 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2536 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2537 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2538 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2539 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2540 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2541 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2542 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2543 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2544 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2545 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2546 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2547 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2548 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2549 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2550 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2551 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2552 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2553 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2554 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2555 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2556 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2557 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2558 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2559 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2560 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2561 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2562 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2563 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2564 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2565 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2566 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2567 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2568 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2569 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2570 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2571 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2572 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2573 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2574 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2575 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2576 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2577 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2578 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2579 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2580 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2581 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2582 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2583 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2584 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2585 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2586 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2587 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2588 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2589 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2590 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2591 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2592 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2593 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2594 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2595 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2596 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2597 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2598 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2599 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2600 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2601 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2602 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2603 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2604 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2605 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2606 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2607 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2608 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2609 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2610 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2611 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2612 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2613 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2614 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2615 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2616 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2617 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2618 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2619 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2620 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2621 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2622 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2623 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2624 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2625 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2626 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2627 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2628 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2629 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2630 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2631 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2632 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2633 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2634 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2635 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2636 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2637 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2638 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2639 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2640 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2641 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2642 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2643 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2644 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2645 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2646 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2647 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2648 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2649 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2650 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2651 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2652 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2653 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2654 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2655 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2656 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2657 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2658 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2659 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2660 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2661 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2662 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2663 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2664 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2665 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2666 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2667 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2668 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2669 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2670 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2671 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2672 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2673 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2674 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2675 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2676 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2677 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2678 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2679 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2680 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2681 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2682 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2683 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2684 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2685 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2686 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2687 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2688 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2689 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2690 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2691 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2692 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2693 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2694 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2695 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2696 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2697 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2698 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2699 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2700 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2701 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2702 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2703 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2704 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2705 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2706 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2707 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2708 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2709 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2710 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2711 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2712 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2713 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2714 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2715 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2716 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2717 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2718 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2719 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2720 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2721 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2722 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2723 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2724 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2725 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2726 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2727 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2728 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2729 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2730 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2731 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2732 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2733 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2734 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2735 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2736 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2737 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2738 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2739 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2740 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2741 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2742 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2743 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2744 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2745 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2746 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2747 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2748 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2749 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2750 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2751 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2752 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2753 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2754 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2755 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2756 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2757 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2758 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2759 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2760 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2761 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2762 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2763 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2764 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2765 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2766 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2767 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2768 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2769 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2770 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2771 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2772 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2773 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2774 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2775 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2776 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2777 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2778 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2779 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2780 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2781 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2782 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2783 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2784 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2785 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2786 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2787 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2788 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2789 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2790 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2791 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2792 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2793 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2794 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2795 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2796 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2797 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2798 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2799 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2800 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2801 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2802 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2803 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2804 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2805 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2806 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2807 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2808 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2809 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2810 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2811 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2812 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2813 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2814 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2815 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2816 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2817 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2818 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2819 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2820 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2821 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2822 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2823 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2824 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2825 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2826 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2827 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2828 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2829 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2830 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2831 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2832 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2833 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2834 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2835 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2836 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2837 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2838 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2839 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2840 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2841 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2842 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2843 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2844 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2845 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2846 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2847 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2848 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2849 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2850 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2851 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2852 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2853 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2854 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2855 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2856 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2857 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2858 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2859 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2860 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2861 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2862 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2863 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2864 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2865 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2866 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2867 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2868 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2869 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2870 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2871 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2872 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2873 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2874 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2875 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2876 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2877 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2878 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2879 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2880 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2881 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2882 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2883 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2884 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2885 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2886 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2887 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2888 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2889 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2890 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2891 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2892 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2893 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2894 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2895 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2896 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2897 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2898 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2899 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2900 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2901 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2902 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2903 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2904 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2905 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2906 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2907 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2908 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2909 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2910 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2911 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2912 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2913 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2914 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2915 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2916 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2917 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2918 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2919 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2920 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2921 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2922 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2923 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2924 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2925 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2926 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2927 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2928 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2929 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2930 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2931 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2932 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2933 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2934 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2935 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2936 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2937 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2938 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2939 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2940 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2941 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2942 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2943 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2944 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2945 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2946 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2947 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2948 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2949 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2950 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2951 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2952 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2953 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2954 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2955 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2956 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2957 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2958 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2959 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2960 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2961 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2962 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2963 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2964 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2965 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2966 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2967 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2968 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2969 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2970 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2971 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2972 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2973 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2974 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2975 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2976 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2977 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2978 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2979 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2980 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2981 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2982 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2983 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2984 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2985 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2986 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2987 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2988 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2989 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2990 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2991 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2992 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2993 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2994 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2995 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2996 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2997 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2998 {}
+ @Retention(RetentionPolicy.RUNTIME) @interface B2999 {}
+
+ @B0
+ @B1
+ @B2
+ @B3
+ @B4
+ @B5
+ @B6
+ @B7
+ @B8
+ @B9
+ @B10
+ @B11
+ @B12
+ @B13
+ @B14
+ @B15
+ @B16
+ @B17
+ @B18
+ @B19
+ @B20
+ @B21
+ @B22
+ @B23
+ @B24
+ @B25
+ @B26
+ @B27
+ @B28
+ @B29
+ @B30
+ @B31
+ @B32
+ @B33
+ @B34
+ @B35
+ @B36
+ @B37
+ @B38
+ @B39
+ @B40
+ @B41
+ @B42
+ @B43
+ @B44
+ @B45
+ @B46
+ @B47
+ @B48
+ @B49
+ @B50
+ @B51
+ @B52
+ @B53
+ @B54
+ @B55
+ @B56
+ @B57
+ @B58
+ @B59
+ @B60
+ @B61
+ @B62
+ @B63
+ @B64
+ @B65
+ @B66
+ @B67
+ @B68
+ @B69
+ @B70
+ @B71
+ @B72
+ @B73
+ @B74
+ @B75
+ @B76
+ @B77
+ @B78
+ @B79
+ @B80
+ @B81
+ @B82
+ @B83
+ @B84
+ @B85
+ @B86
+ @B87
+ @B88
+ @B89
+ @B90
+ @B91
+ @B92
+ @B93
+ @B94
+ @B95
+ @B96
+ @B97
+ @B98
+ @B99
+ @B100
+ @B101
+ @B102
+ @B103
+ @B104
+ @B105
+ @B106
+ @B107
+ @B108
+ @B109
+ @B110
+ @B111
+ @B112
+ @B113
+ @B114
+ @B115
+ @B116
+ @B117
+ @B118
+ @B119
+ @B120
+ @B121
+ @B122
+ @B123
+ @B124
+ @B125
+ @B126
+ @B127
+ @B128
+ @B129
+ @B130
+ @B131
+ @B132
+ @B133
+ @B134
+ @B135
+ @B136
+ @B137
+ @B138
+ @B139
+ @B140
+ @B141
+ @B142
+ @B143
+ @B144
+ @B145
+ @B146
+ @B147
+ @B148
+ @B149
+ @B150
+ @B151
+ @B152
+ @B153
+ @B154
+ @B155
+ @B156
+ @B157
+ @B158
+ @B159
+ @B160
+ @B161
+ @B162
+ @B163
+ @B164
+ @B165
+ @B166
+ @B167
+ @B168
+ @B169
+ @B170
+ @B171
+ @B172
+ @B173
+ @B174
+ @B175
+ @B176
+ @B177
+ @B178
+ @B179
+ @B180
+ @B181
+ @B182
+ @B183
+ @B184
+ @B185
+ @B186
+ @B187
+ @B188
+ @B189
+ @B190
+ @B191
+ @B192
+ @B193
+ @B194
+ @B195
+ @B196
+ @B197
+ @B198
+ @B199
+ @B200
+ @B201
+ @B202
+ @B203
+ @B204
+ @B205
+ @B206
+ @B207
+ @B208
+ @B209
+ @B210
+ @B211
+ @B212
+ @B213
+ @B214
+ @B215
+ @B216
+ @B217
+ @B218
+ @B219
+ @B220
+ @B221
+ @B222
+ @B223
+ @B224
+ @B225
+ @B226
+ @B227
+ @B228
+ @B229
+ @B230
+ @B231
+ @B232
+ @B233
+ @B234
+ @B235
+ @B236
+ @B237
+ @B238
+ @B239
+ @B240
+ @B241
+ @B242
+ @B243
+ @B244
+ @B245
+ @B246
+ @B247
+ @B248
+ @B249
+ @B250
+ @B251
+ @B252
+ @B253
+ @B254
+ @B255
+ @B256
+ @B257
+ @B258
+ @B259
+ @B260
+ @B261
+ @B262
+ @B263
+ @B264
+ @B265
+ @B266
+ @B267
+ @B268
+ @B269
+ @B270
+ @B271
+ @B272
+ @B273
+ @B274
+ @B275
+ @B276
+ @B277
+ @B278
+ @B279
+ @B280
+ @B281
+ @B282
+ @B283
+ @B284
+ @B285
+ @B286
+ @B287
+ @B288
+ @B289
+ @B290
+ @B291
+ @B292
+ @B293
+ @B294
+ @B295
+ @B296
+ @B297
+ @B298
+ @B299
+ @B300
+ @B301
+ @B302
+ @B303
+ @B304
+ @B305
+ @B306
+ @B307
+ @B308
+ @B309
+ @B310
+ @B311
+ @B312
+ @B313
+ @B314
+ @B315
+ @B316
+ @B317
+ @B318
+ @B319
+ @B320
+ @B321
+ @B322
+ @B323
+ @B324
+ @B325
+ @B326
+ @B327
+ @B328
+ @B329
+ @B330
+ @B331
+ @B332
+ @B333
+ @B334
+ @B335
+ @B336
+ @B337
+ @B338
+ @B339
+ @B340
+ @B341
+ @B342
+ @B343
+ @B344
+ @B345
+ @B346
+ @B347
+ @B348
+ @B349
+ @B350
+ @B351
+ @B352
+ @B353
+ @B354
+ @B355
+ @B356
+ @B357
+ @B358
+ @B359
+ @B360
+ @B361
+ @B362
+ @B363
+ @B364
+ @B365
+ @B366
+ @B367
+ @B368
+ @B369
+ @B370
+ @B371
+ @B372
+ @B373
+ @B374
+ @B375
+ @B376
+ @B377
+ @B378
+ @B379
+ @B380
+ @B381
+ @B382
+ @B383
+ @B384
+ @B385
+ @B386
+ @B387
+ @B388
+ @B389
+ @B390
+ @B391
+ @B392
+ @B393
+ @B394
+ @B395
+ @B396
+ @B397
+ @B398
+ @B399
+ @B400
+ @B401
+ @B402
+ @B403
+ @B404
+ @B405
+ @B406
+ @B407
+ @B408
+ @B409
+ @B410
+ @B411
+ @B412
+ @B413
+ @B414
+ @B415
+ @B416
+ @B417
+ @B418
+ @B419
+ @B420
+ @B421
+ @B422
+ @B423
+ @B424
+ @B425
+ @B426
+ @B427
+ @B428
+ @B429
+ @B430
+ @B431
+ @B432
+ @B433
+ @B434
+ @B435
+ @B436
+ @B437
+ @B438
+ @B439
+ @B440
+ @B441
+ @B442
+ @B443
+ @B444
+ @B445
+ @B446
+ @B447
+ @B448
+ @B449
+ @B450
+ @B451
+ @B452
+ @B453
+ @B454
+ @B455
+ @B456
+ @B457
+ @B458
+ @B459
+ @B460
+ @B461
+ @B462
+ @B463
+ @B464
+ @B465
+ @B466
+ @B467
+ @B468
+ @B469
+ @B470
+ @B471
+ @B472
+ @B473
+ @B474
+ @B475
+ @B476
+ @B477
+ @B478
+ @B479
+ @B480
+ @B481
+ @B482
+ @B483
+ @B484
+ @B485
+ @B486
+ @B487
+ @B488
+ @B489
+ @B490
+ @B491
+ @B492
+ @B493
+ @B494
+ @B495
+ @B496
+ @B497
+ @B498
+ @B499
+ @B500
+ @B501
+ @B502
+ @B503
+ @B504
+ @B505
+ @B506
+ @B507
+ @B508
+ @B509
+ @B510
+ @B511
+ @B512
+ @B513
+ @B514
+ @B515
+ @B516
+ @B517
+ @B518
+ @B519
+ @B520
+ @B521
+ @B522
+ @B523
+ @B524
+ @B525
+ @B526
+ @B527
+ @B528
+ @B529
+ @B530
+ @B531
+ @B532
+ @B533
+ @B534
+ @B535
+ @B536
+ @B537
+ @B538
+ @B539
+ @B540
+ @B541
+ @B542
+ @B543
+ @B544
+ @B545
+ @B546
+ @B547
+ @B548
+ @B549
+ @B550
+ @B551
+ @B552
+ @B553
+ @B554
+ @B555
+ @B556
+ @B557
+ @B558
+ @B559
+ @B560
+ @B561
+ @B562
+ @B563
+ @B564
+ @B565
+ @B566
+ @B567
+ @B568
+ @B569
+ @B570
+ @B571
+ @B572
+ @B573
+ @B574
+ @B575
+ @B576
+ @B577
+ @B578
+ @B579
+ @B580
+ @B581
+ @B582
+ @B583
+ @B584
+ @B585
+ @B586
+ @B587
+ @B588
+ @B589
+ @B590
+ @B591
+ @B592
+ @B593
+ @B594
+ @B595
+ @B596
+ @B597
+ @B598
+ @B599
+ @B600
+ @B601
+ @B602
+ @B603
+ @B604
+ @B605
+ @B606
+ @B607
+ @B608
+ @B609
+ @B610
+ @B611
+ @B612
+ @B613
+ @B614
+ @B615
+ @B616
+ @B617
+ @B618
+ @B619
+ @B620
+ @B621
+ @B622
+ @B623
+ @B624
+ @B625
+ @B626
+ @B627
+ @B628
+ @B629
+ @B630
+ @B631
+ @B632
+ @B633
+ @B634
+ @B635
+ @B636
+ @B637
+ @B638
+ @B639
+ @B640
+ @B641
+ @B642
+ @B643
+ @B644
+ @B645
+ @B646
+ @B647
+ @B648
+ @B649
+ @B650
+ @B651
+ @B652
+ @B653
+ @B654
+ @B655
+ @B656
+ @B657
+ @B658
+ @B659
+ @B660
+ @B661
+ @B662
+ @B663
+ @B664
+ @B665
+ @B666
+ @B667
+ @B668
+ @B669
+ @B670
+ @B671
+ @B672
+ @B673
+ @B674
+ @B675
+ @B676
+ @B677
+ @B678
+ @B679
+ @B680
+ @B681
+ @B682
+ @B683
+ @B684
+ @B685
+ @B686
+ @B687
+ @B688
+ @B689
+ @B690
+ @B691
+ @B692
+ @B693
+ @B694
+ @B695
+ @B696
+ @B697
+ @B698
+ @B699
+ @B700
+ @B701
+ @B702
+ @B703
+ @B704
+ @B705
+ @B706
+ @B707
+ @B708
+ @B709
+ @B710
+ @B711
+ @B712
+ @B713
+ @B714
+ @B715
+ @B716
+ @B717
+ @B718
+ @B719
+ @B720
+ @B721
+ @B722
+ @B723
+ @B724
+ @B725
+ @B726
+ @B727
+ @B728
+ @B729
+ @B730
+ @B731
+ @B732
+ @B733
+ @B734
+ @B735
+ @B736
+ @B737
+ @B738
+ @B739
+ @B740
+ @B741
+ @B742
+ @B743
+ @B744
+ @B745
+ @B746
+ @B747
+ @B748
+ @B749
+ @B750
+ @B751
+ @B752
+ @B753
+ @B754
+ @B755
+ @B756
+ @B757
+ @B758
+ @B759
+ @B760
+ @B761
+ @B762
+ @B763
+ @B764
+ @B765
+ @B766
+ @B767
+ @B768
+ @B769
+ @B770
+ @B771
+ @B772
+ @B773
+ @B774
+ @B775
+ @B776
+ @B777
+ @B778
+ @B779
+ @B780
+ @B781
+ @B782
+ @B783
+ @B784
+ @B785
+ @B786
+ @B787
+ @B788
+ @B789
+ @B790
+ @B791
+ @B792
+ @B793
+ @B794
+ @B795
+ @B796
+ @B797
+ @B798
+ @B799
+ @B800
+ @B801
+ @B802
+ @B803
+ @B804
+ @B805
+ @B806
+ @B807
+ @B808
+ @B809
+ @B810
+ @B811
+ @B812
+ @B813
+ @B814
+ @B815
+ @B816
+ @B817
+ @B818
+ @B819
+ @B820
+ @B821
+ @B822
+ @B823
+ @B824
+ @B825
+ @B826
+ @B827
+ @B828
+ @B829
+ @B830
+ @B831
+ @B832
+ @B833
+ @B834
+ @B835
+ @B836
+ @B837
+ @B838
+ @B839
+ @B840
+ @B841
+ @B842
+ @B843
+ @B844
+ @B845
+ @B846
+ @B847
+ @B848
+ @B849
+ @B850
+ @B851
+ @B852
+ @B853
+ @B854
+ @B855
+ @B856
+ @B857
+ @B858
+ @B859
+ @B860
+ @B861
+ @B862
+ @B863
+ @B864
+ @B865
+ @B866
+ @B867
+ @B868
+ @B869
+ @B870
+ @B871
+ @B872
+ @B873
+ @B874
+ @B875
+ @B876
+ @B877
+ @B878
+ @B879
+ @B880
+ @B881
+ @B882
+ @B883
+ @B884
+ @B885
+ @B886
+ @B887
+ @B888
+ @B889
+ @B890
+ @B891
+ @B892
+ @B893
+ @B894
+ @B895
+ @B896
+ @B897
+ @B898
+ @B899
+ @B900
+ @B901
+ @B902
+ @B903
+ @B904
+ @B905
+ @B906
+ @B907
+ @B908
+ @B909
+ @B910
+ @B911
+ @B912
+ @B913
+ @B914
+ @B915
+ @B916
+ @B917
+ @B918
+ @B919
+ @B920
+ @B921
+ @B922
+ @B923
+ @B924
+ @B925
+ @B926
+ @B927
+ @B928
+ @B929
+ @B930
+ @B931
+ @B932
+ @B933
+ @B934
+ @B935
+ @B936
+ @B937
+ @B938
+ @B939
+ @B940
+ @B941
+ @B942
+ @B943
+ @B944
+ @B945
+ @B946
+ @B947
+ @B948
+ @B949
+ @B950
+ @B951
+ @B952
+ @B953
+ @B954
+ @B955
+ @B956
+ @B957
+ @B958
+ @B959
+ @B960
+ @B961
+ @B962
+ @B963
+ @B964
+ @B965
+ @B966
+ @B967
+ @B968
+ @B969
+ @B970
+ @B971
+ @B972
+ @B973
+ @B974
+ @B975
+ @B976
+ @B977
+ @B978
+ @B979
+ @B980
+ @B981
+ @B982
+ @B983
+ @B984
+ @B985
+ @B986
+ @B987
+ @B988
+ @B989
+ @B990
+ @B991
+ @B992
+ @B993
+ @B994
+ @B995
+ @B996
+ @B997
+ @B998
+ @B999
+ @B1000
+ @B1001
+ @B1002
+ @B1003
+ @B1004
+ @B1005
+ @B1006
+ @B1007
+ @B1008
+ @B1009
+ @B1010
+ @B1011
+ @B1012
+ @B1013
+ @B1014
+ @B1015
+ @B1016
+ @B1017
+ @B1018
+ @B1019
+ @B1020
+ @B1021
+ @B1022
+ @B1023
+ @B1024
+ @B1025
+ @B1026
+ @B1027
+ @B1028
+ @B1029
+ @B1030
+ @B1031
+ @B1032
+ @B1033
+ @B1034
+ @B1035
+ @B1036
+ @B1037
+ @B1038
+ @B1039
+ @B1040
+ @B1041
+ @B1042
+ @B1043
+ @B1044
+ @B1045
+ @B1046
+ @B1047
+ @B1048
+ @B1049
+ @B1050
+ @B1051
+ @B1052
+ @B1053
+ @B1054
+ @B1055
+ @B1056
+ @B1057
+ @B1058
+ @B1059
+ @B1060
+ @B1061
+ @B1062
+ @B1063
+ @B1064
+ @B1065
+ @B1066
+ @B1067
+ @B1068
+ @B1069
+ @B1070
+ @B1071
+ @B1072
+ @B1073
+ @B1074
+ @B1075
+ @B1076
+ @B1077
+ @B1078
+ @B1079
+ @B1080
+ @B1081
+ @B1082
+ @B1083
+ @B1084
+ @B1085
+ @B1086
+ @B1087
+ @B1088
+ @B1089
+ @B1090
+ @B1091
+ @B1092
+ @B1093
+ @B1094
+ @B1095
+ @B1096
+ @B1097
+ @B1098
+ @B1099
+ @B1100
+ @B1101
+ @B1102
+ @B1103
+ @B1104
+ @B1105
+ @B1106
+ @B1107
+ @B1108
+ @B1109
+ @B1110
+ @B1111
+ @B1112
+ @B1113
+ @B1114
+ @B1115
+ @B1116
+ @B1117
+ @B1118
+ @B1119
+ @B1120
+ @B1121
+ @B1122
+ @B1123
+ @B1124
+ @B1125
+ @B1126
+ @B1127
+ @B1128
+ @B1129
+ @B1130
+ @B1131
+ @B1132
+ @B1133
+ @B1134
+ @B1135
+ @B1136
+ @B1137
+ @B1138
+ @B1139
+ @B1140
+ @B1141
+ @B1142
+ @B1143
+ @B1144
+ @B1145
+ @B1146
+ @B1147
+ @B1148
+ @B1149
+ @B1150
+ @B1151
+ @B1152
+ @B1153
+ @B1154
+ @B1155
+ @B1156
+ @B1157
+ @B1158
+ @B1159
+ @B1160
+ @B1161
+ @B1162
+ @B1163
+ @B1164
+ @B1165
+ @B1166
+ @B1167
+ @B1168
+ @B1169
+ @B1170
+ @B1171
+ @B1172
+ @B1173
+ @B1174
+ @B1175
+ @B1176
+ @B1177
+ @B1178
+ @B1179
+ @B1180
+ @B1181
+ @B1182
+ @B1183
+ @B1184
+ @B1185
+ @B1186
+ @B1187
+ @B1188
+ @B1189
+ @B1190
+ @B1191
+ @B1192
+ @B1193
+ @B1194
+ @B1195
+ @B1196
+ @B1197
+ @B1198
+ @B1199
+ @B1200
+ @B1201
+ @B1202
+ @B1203
+ @B1204
+ @B1205
+ @B1206
+ @B1207
+ @B1208
+ @B1209
+ @B1210
+ @B1211
+ @B1212
+ @B1213
+ @B1214
+ @B1215
+ @B1216
+ @B1217
+ @B1218
+ @B1219
+ @B1220
+ @B1221
+ @B1222
+ @B1223
+ @B1224
+ @B1225
+ @B1226
+ @B1227
+ @B1228
+ @B1229
+ @B1230
+ @B1231
+ @B1232
+ @B1233
+ @B1234
+ @B1235
+ @B1236
+ @B1237
+ @B1238
+ @B1239
+ @B1240
+ @B1241
+ @B1242
+ @B1243
+ @B1244
+ @B1245
+ @B1246
+ @B1247
+ @B1248
+ @B1249
+ @B1250
+ @B1251
+ @B1252
+ @B1253
+ @B1254
+ @B1255
+ @B1256
+ @B1257
+ @B1258
+ @B1259
+ @B1260
+ @B1261
+ @B1262
+ @B1263
+ @B1264
+ @B1265
+ @B1266
+ @B1267
+ @B1268
+ @B1269
+ @B1270
+ @B1271
+ @B1272
+ @B1273
+ @B1274
+ @B1275
+ @B1276
+ @B1277
+ @B1278
+ @B1279
+ @B1280
+ @B1281
+ @B1282
+ @B1283
+ @B1284
+ @B1285
+ @B1286
+ @B1287
+ @B1288
+ @B1289
+ @B1290
+ @B1291
+ @B1292
+ @B1293
+ @B1294
+ @B1295
+ @B1296
+ @B1297
+ @B1298
+ @B1299
+ @B1300
+ @B1301
+ @B1302
+ @B1303
+ @B1304
+ @B1305
+ @B1306
+ @B1307
+ @B1308
+ @B1309
+ @B1310
+ @B1311
+ @B1312
+ @B1313
+ @B1314
+ @B1315
+ @B1316
+ @B1317
+ @B1318
+ @B1319
+ @B1320
+ @B1321
+ @B1322
+ @B1323
+ @B1324
+ @B1325
+ @B1326
+ @B1327
+ @B1328
+ @B1329
+ @B1330
+ @B1331
+ @B1332
+ @B1333
+ @B1334
+ @B1335
+ @B1336
+ @B1337
+ @B1338
+ @B1339
+ @B1340
+ @B1341
+ @B1342
+ @B1343
+ @B1344
+ @B1345
+ @B1346
+ @B1347
+ @B1348
+ @B1349
+ @B1350
+ @B1351
+ @B1352
+ @B1353
+ @B1354
+ @B1355
+ @B1356
+ @B1357
+ @B1358
+ @B1359
+ @B1360
+ @B1361
+ @B1362
+ @B1363
+ @B1364
+ @B1365
+ @B1366
+ @B1367
+ @B1368
+ @B1369
+ @B1370
+ @B1371
+ @B1372
+ @B1373
+ @B1374
+ @B1375
+ @B1376
+ @B1377
+ @B1378
+ @B1379
+ @B1380
+ @B1381
+ @B1382
+ @B1383
+ @B1384
+ @B1385
+ @B1386
+ @B1387
+ @B1388
+ @B1389
+ @B1390
+ @B1391
+ @B1392
+ @B1393
+ @B1394
+ @B1395
+ @B1396
+ @B1397
+ @B1398
+ @B1399
+ @B1400
+ @B1401
+ @B1402
+ @B1403
+ @B1404
+ @B1405
+ @B1406
+ @B1407
+ @B1408
+ @B1409
+ @B1410
+ @B1411
+ @B1412
+ @B1413
+ @B1414
+ @B1415
+ @B1416
+ @B1417
+ @B1418
+ @B1419
+ @B1420
+ @B1421
+ @B1422
+ @B1423
+ @B1424
+ @B1425
+ @B1426
+ @B1427
+ @B1428
+ @B1429
+ @B1430
+ @B1431
+ @B1432
+ @B1433
+ @B1434
+ @B1435
+ @B1436
+ @B1437
+ @B1438
+ @B1439
+ @B1440
+ @B1441
+ @B1442
+ @B1443
+ @B1444
+ @B1445
+ @B1446
+ @B1447
+ @B1448
+ @B1449
+ @B1450
+ @B1451
+ @B1452
+ @B1453
+ @B1454
+ @B1455
+ @B1456
+ @B1457
+ @B1458
+ @B1459
+ @B1460
+ @B1461
+ @B1462
+ @B1463
+ @B1464
+ @B1465
+ @B1466
+ @B1467
+ @B1468
+ @B1469
+ @B1470
+ @B1471
+ @B1472
+ @B1473
+ @B1474
+ @B1475
+ @B1476
+ @B1477
+ @B1478
+ @B1479
+ @B1480
+ @B1481
+ @B1482
+ @B1483
+ @B1484
+ @B1485
+ @B1486
+ @B1487
+ @B1488
+ @B1489
+ @B1490
+ @B1491
+ @B1492
+ @B1493
+ @B1494
+ @B1495
+ @B1496
+ @B1497
+ @B1498
+ @B1499
+ @B1500
+ @B1501
+ @B1502
+ @B1503
+ @B1504
+ @B1505
+ @B1506
+ @B1507
+ @B1508
+ @B1509
+ @B1510
+ @B1511
+ @B1512
+ @B1513
+ @B1514
+ @B1515
+ @B1516
+ @B1517
+ @B1518
+ @B1519
+ @B1520
+ @B1521
+ @B1522
+ @B1523
+ @B1524
+ @B1525
+ @B1526
+ @B1527
+ @B1528
+ @B1529
+ @B1530
+ @B1531
+ @B1532
+ @B1533
+ @B1534
+ @B1535
+ @B1536
+ @B1537
+ @B1538
+ @B1539
+ @B1540
+ @B1541
+ @B1542
+ @B1543
+ @B1544
+ @B1545
+ @B1546
+ @B1547
+ @B1548
+ @B1549
+ @B1550
+ @B1551
+ @B1552
+ @B1553
+ @B1554
+ @B1555
+ @B1556
+ @B1557
+ @B1558
+ @B1559
+ @B1560
+ @B1561
+ @B1562
+ @B1563
+ @B1564
+ @B1565
+ @B1566
+ @B1567
+ @B1568
+ @B1569
+ @B1570
+ @B1571
+ @B1572
+ @B1573
+ @B1574
+ @B1575
+ @B1576
+ @B1577
+ @B1578
+ @B1579
+ @B1580
+ @B1581
+ @B1582
+ @B1583
+ @B1584
+ @B1585
+ @B1586
+ @B1587
+ @B1588
+ @B1589
+ @B1590
+ @B1591
+ @B1592
+ @B1593
+ @B1594
+ @B1595
+ @B1596
+ @B1597
+ @B1598
+ @B1599
+ @B1600
+ @B1601
+ @B1602
+ @B1603
+ @B1604
+ @B1605
+ @B1606
+ @B1607
+ @B1608
+ @B1609
+ @B1610
+ @B1611
+ @B1612
+ @B1613
+ @B1614
+ @B1615
+ @B1616
+ @B1617
+ @B1618
+ @B1619
+ @B1620
+ @B1621
+ @B1622
+ @B1623
+ @B1624
+ @B1625
+ @B1626
+ @B1627
+ @B1628
+ @B1629
+ @B1630
+ @B1631
+ @B1632
+ @B1633
+ @B1634
+ @B1635
+ @B1636
+ @B1637
+ @B1638
+ @B1639
+ @B1640
+ @B1641
+ @B1642
+ @B1643
+ @B1644
+ @B1645
+ @B1646
+ @B1647
+ @B1648
+ @B1649
+ @B1650
+ @B1651
+ @B1652
+ @B1653
+ @B1654
+ @B1655
+ @B1656
+ @B1657
+ @B1658
+ @B1659
+ @B1660
+ @B1661
+ @B1662
+ @B1663
+ @B1664
+ @B1665
+ @B1666
+ @B1667
+ @B1668
+ @B1669
+ @B1670
+ @B1671
+ @B1672
+ @B1673
+ @B1674
+ @B1675
+ @B1676
+ @B1677
+ @B1678
+ @B1679
+ @B1680
+ @B1681
+ @B1682
+ @B1683
+ @B1684
+ @B1685
+ @B1686
+ @B1687
+ @B1688
+ @B1689
+ @B1690
+ @B1691
+ @B1692
+ @B1693
+ @B1694
+ @B1695
+ @B1696
+ @B1697
+ @B1698
+ @B1699
+ @B1700
+ @B1701
+ @B1702
+ @B1703
+ @B1704
+ @B1705
+ @B1706
+ @B1707
+ @B1708
+ @B1709
+ @B1710
+ @B1711
+ @B1712
+ @B1713
+ @B1714
+ @B1715
+ @B1716
+ @B1717
+ @B1718
+ @B1719
+ @B1720
+ @B1721
+ @B1722
+ @B1723
+ @B1724
+ @B1725
+ @B1726
+ @B1727
+ @B1728
+ @B1729
+ @B1730
+ @B1731
+ @B1732
+ @B1733
+ @B1734
+ @B1735
+ @B1736
+ @B1737
+ @B1738
+ @B1739
+ @B1740
+ @B1741
+ @B1742
+ @B1743
+ @B1744
+ @B1745
+ @B1746
+ @B1747
+ @B1748
+ @B1749
+ @B1750
+ @B1751
+ @B1752
+ @B1753
+ @B1754
+ @B1755
+ @B1756
+ @B1757
+ @B1758
+ @B1759
+ @B1760
+ @B1761
+ @B1762
+ @B1763
+ @B1764
+ @B1765
+ @B1766
+ @B1767
+ @B1768
+ @B1769
+ @B1770
+ @B1771
+ @B1772
+ @B1773
+ @B1774
+ @B1775
+ @B1776
+ @B1777
+ @B1778
+ @B1779
+ @B1780
+ @B1781
+ @B1782
+ @B1783
+ @B1784
+ @B1785
+ @B1786
+ @B1787
+ @B1788
+ @B1789
+ @B1790
+ @B1791
+ @B1792
+ @B1793
+ @B1794
+ @B1795
+ @B1796
+ @B1797
+ @B1798
+ @B1799
+ @B1800
+ @B1801
+ @B1802
+ @B1803
+ @B1804
+ @B1805
+ @B1806
+ @B1807
+ @B1808
+ @B1809
+ @B1810
+ @B1811
+ @B1812
+ @B1813
+ @B1814
+ @B1815
+ @B1816
+ @B1817
+ @B1818
+ @B1819
+ @B1820
+ @B1821
+ @B1822
+ @B1823
+ @B1824
+ @B1825
+ @B1826
+ @B1827
+ @B1828
+ @B1829
+ @B1830
+ @B1831
+ @B1832
+ @B1833
+ @B1834
+ @B1835
+ @B1836
+ @B1837
+ @B1838
+ @B1839
+ @B1840
+ @B1841
+ @B1842
+ @B1843
+ @B1844
+ @B1845
+ @B1846
+ @B1847
+ @B1848
+ @B1849
+ @B1850
+ @B1851
+ @B1852
+ @B1853
+ @B1854
+ @B1855
+ @B1856
+ @B1857
+ @B1858
+ @B1859
+ @B1860
+ @B1861
+ @B1862
+ @B1863
+ @B1864
+ @B1865
+ @B1866
+ @B1867
+ @B1868
+ @B1869
+ @B1870
+ @B1871
+ @B1872
+ @B1873
+ @B1874
+ @B1875
+ @B1876
+ @B1877
+ @B1878
+ @B1879
+ @B1880
+ @B1881
+ @B1882
+ @B1883
+ @B1884
+ @B1885
+ @B1886
+ @B1887
+ @B1888
+ @B1889
+ @B1890
+ @B1891
+ @B1892
+ @B1893
+ @B1894
+ @B1895
+ @B1896
+ @B1897
+ @B1898
+ @B1899
+ @B1900
+ @B1901
+ @B1902
+ @B1903
+ @B1904
+ @B1905
+ @B1906
+ @B1907
+ @B1908
+ @B1909
+ @B1910
+ @B1911
+ @B1912
+ @B1913
+ @B1914
+ @B1915
+ @B1916
+ @B1917
+ @B1918
+ @B1919
+ @B1920
+ @B1921
+ @B1922
+ @B1923
+ @B1924
+ @B1925
+ @B1926
+ @B1927
+ @B1928
+ @B1929
+ @B1930
+ @B1931
+ @B1932
+ @B1933
+ @B1934
+ @B1935
+ @B1936
+ @B1937
+ @B1938
+ @B1939
+ @B1940
+ @B1941
+ @B1942
+ @B1943
+ @B1944
+ @B1945
+ @B1946
+ @B1947
+ @B1948
+ @B1949
+ @B1950
+ @B1951
+ @B1952
+ @B1953
+ @B1954
+ @B1955
+ @B1956
+ @B1957
+ @B1958
+ @B1959
+ @B1960
+ @B1961
+ @B1962
+ @B1963
+ @B1964
+ @B1965
+ @B1966
+ @B1967
+ @B1968
+ @B1969
+ @B1970
+ @B1971
+ @B1972
+ @B1973
+ @B1974
+ @B1975
+ @B1976
+ @B1977
+ @B1978
+ @B1979
+ @B1980
+ @B1981
+ @B1982
+ @B1983
+ @B1984
+ @B1985
+ @B1986
+ @B1987
+ @B1988
+ @B1989
+ @B1990
+ @B1991
+ @B1992
+ @B1993
+ @B1994
+ @B1995
+ @B1996
+ @B1997
+ @B1998
+ @B1999
+ @B2000
+ @B2001
+ @B2002
+ @B2003
+ @B2004
+ @B2005
+ @B2006
+ @B2007
+ @B2008
+ @B2009
+ @B2010
+ @B2011
+ @B2012
+ @B2013
+ @B2014
+ @B2015
+ @B2016
+ @B2017
+ @B2018
+ @B2019
+ @B2020
+ @B2021
+ @B2022
+ @B2023
+ @B2024
+ @B2025
+ @B2026
+ @B2027
+ @B2028
+ @B2029
+ @B2030
+ @B2031
+ @B2032
+ @B2033
+ @B2034
+ @B2035
+ @B2036
+ @B2037
+ @B2038
+ @B2039
+ @B2040
+ @B2041
+ @B2042
+ @B2043
+ @B2044
+ @B2045
+ @B2046
+ @B2047
+ @B2048
+ @B2049
+ @B2050
+ @B2051
+ @B2052
+ @B2053
+ @B2054
+ @B2055
+ @B2056
+ @B2057
+ @B2058
+ @B2059
+ @B2060
+ @B2061
+ @B2062
+ @B2063
+ @B2064
+ @B2065
+ @B2066
+ @B2067
+ @B2068
+ @B2069
+ @B2070
+ @B2071
+ @B2072
+ @B2073
+ @B2074
+ @B2075
+ @B2076
+ @B2077
+ @B2078
+ @B2079
+ @B2080
+ @B2081
+ @B2082
+ @B2083
+ @B2084
+ @B2085
+ @B2086
+ @B2087
+ @B2088
+ @B2089
+ @B2090
+ @B2091
+ @B2092
+ @B2093
+ @B2094
+ @B2095
+ @B2096
+ @B2097
+ @B2098
+ @B2099
+ @B2100
+ @B2101
+ @B2102
+ @B2103
+ @B2104
+ @B2105
+ @B2106
+ @B2107
+ @B2108
+ @B2109
+ @B2110
+ @B2111
+ @B2112
+ @B2113
+ @B2114
+ @B2115
+ @B2116
+ @B2117
+ @B2118
+ @B2119
+ @B2120
+ @B2121
+ @B2122
+ @B2123
+ @B2124
+ @B2125
+ @B2126
+ @B2127
+ @B2128
+ @B2129
+ @B2130
+ @B2131
+ @B2132
+ @B2133
+ @B2134
+ @B2135
+ @B2136
+ @B2137
+ @B2138
+ @B2139
+ @B2140
+ @B2141
+ @B2142
+ @B2143
+ @B2144
+ @B2145
+ @B2146
+ @B2147
+ @B2148
+ @B2149
+ @B2150
+ @B2151
+ @B2152
+ @B2153
+ @B2154
+ @B2155
+ @B2156
+ @B2157
+ @B2158
+ @B2159
+ @B2160
+ @B2161
+ @B2162
+ @B2163
+ @B2164
+ @B2165
+ @B2166
+ @B2167
+ @B2168
+ @B2169
+ @B2170
+ @B2171
+ @B2172
+ @B2173
+ @B2174
+ @B2175
+ @B2176
+ @B2177
+ @B2178
+ @B2179
+ @B2180
+ @B2181
+ @B2182
+ @B2183
+ @B2184
+ @B2185
+ @B2186
+ @B2187
+ @B2188
+ @B2189
+ @B2190
+ @B2191
+ @B2192
+ @B2193
+ @B2194
+ @B2195
+ @B2196
+ @B2197
+ @B2198
+ @B2199
+ @B2200
+ @B2201
+ @B2202
+ @B2203
+ @B2204
+ @B2205
+ @B2206
+ @B2207
+ @B2208
+ @B2209
+ @B2210
+ @B2211
+ @B2212
+ @B2213
+ @B2214
+ @B2215
+ @B2216
+ @B2217
+ @B2218
+ @B2219
+ @B2220
+ @B2221
+ @B2222
+ @B2223
+ @B2224
+ @B2225
+ @B2226
+ @B2227
+ @B2228
+ @B2229
+ @B2230
+ @B2231
+ @B2232
+ @B2233
+ @B2234
+ @B2235
+ @B2236
+ @B2237
+ @B2238
+ @B2239
+ @B2240
+ @B2241
+ @B2242
+ @B2243
+ @B2244
+ @B2245
+ @B2246
+ @B2247
+ @B2248
+ @B2249
+ @B2250
+ @B2251
+ @B2252
+ @B2253
+ @B2254
+ @B2255
+ @B2256
+ @B2257
+ @B2258
+ @B2259
+ @B2260
+ @B2261
+ @B2262
+ @B2263
+ @B2264
+ @B2265
+ @B2266
+ @B2267
+ @B2268
+ @B2269
+ @B2270
+ @B2271
+ @B2272
+ @B2273
+ @B2274
+ @B2275
+ @B2276
+ @B2277
+ @B2278
+ @B2279
+ @B2280
+ @B2281
+ @B2282
+ @B2283
+ @B2284
+ @B2285
+ @B2286
+ @B2287
+ @B2288
+ @B2289
+ @B2290
+ @B2291
+ @B2292
+ @B2293
+ @B2294
+ @B2295
+ @B2296
+ @B2297
+ @B2298
+ @B2299
+ @B2300
+ @B2301
+ @B2302
+ @B2303
+ @B2304
+ @B2305
+ @B2306
+ @B2307
+ @B2308
+ @B2309
+ @B2310
+ @B2311
+ @B2312
+ @B2313
+ @B2314
+ @B2315
+ @B2316
+ @B2317
+ @B2318
+ @B2319
+ @B2320
+ @B2321
+ @B2322
+ @B2323
+ @B2324
+ @B2325
+ @B2326
+ @B2327
+ @B2328
+ @B2329
+ @B2330
+ @B2331
+ @B2332
+ @B2333
+ @B2334
+ @B2335
+ @B2336
+ @B2337
+ @B2338
+ @B2339
+ @B2340
+ @B2341
+ @B2342
+ @B2343
+ @B2344
+ @B2345
+ @B2346
+ @B2347
+ @B2348
+ @B2349
+ @B2350
+ @B2351
+ @B2352
+ @B2353
+ @B2354
+ @B2355
+ @B2356
+ @B2357
+ @B2358
+ @B2359
+ @B2360
+ @B2361
+ @B2362
+ @B2363
+ @B2364
+ @B2365
+ @B2366
+ @B2367
+ @B2368
+ @B2369
+ @B2370
+ @B2371
+ @B2372
+ @B2373
+ @B2374
+ @B2375
+ @B2376
+ @B2377
+ @B2378
+ @B2379
+ @B2380
+ @B2381
+ @B2382
+ @B2383
+ @B2384
+ @B2385
+ @B2386
+ @B2387
+ @B2388
+ @B2389
+ @B2390
+ @B2391
+ @B2392
+ @B2393
+ @B2394
+ @B2395
+ @B2396
+ @B2397
+ @B2398
+ @B2399
+ @B2400
+ @B2401
+ @B2402
+ @B2403
+ @B2404
+ @B2405
+ @B2406
+ @B2407
+ @B2408
+ @B2409
+ @B2410
+ @B2411
+ @B2412
+ @B2413
+ @B2414
+ @B2415
+ @B2416
+ @B2417
+ @B2418
+ @B2419
+ @B2420
+ @B2421
+ @B2422
+ @B2423
+ @B2424
+ @B2425
+ @B2426
+ @B2427
+ @B2428
+ @B2429
+ @B2430
+ @B2431
+ @B2432
+ @B2433
+ @B2434
+ @B2435
+ @B2436
+ @B2437
+ @B2438
+ @B2439
+ @B2440
+ @B2441
+ @B2442
+ @B2443
+ @B2444
+ @B2445
+ @B2446
+ @B2447
+ @B2448
+ @B2449
+ @B2450
+ @B2451
+ @B2452
+ @B2453
+ @B2454
+ @B2455
+ @B2456
+ @B2457
+ @B2458
+ @B2459
+ @B2460
+ @B2461
+ @B2462
+ @B2463
+ @B2464
+ @B2465
+ @B2466
+ @B2467
+ @B2468
+ @B2469
+ @B2470
+ @B2471
+ @B2472
+ @B2473
+ @B2474
+ @B2475
+ @B2476
+ @B2477
+ @B2478
+ @B2479
+ @B2480
+ @B2481
+ @B2482
+ @B2483
+ @B2484
+ @B2485
+ @B2486
+ @B2487
+ @B2488
+ @B2489
+ @B2490
+ @B2491
+ @B2492
+ @B2493
+ @B2494
+ @B2495
+ @B2496
+ @B2497
+ @B2498
+ @B2499
+ @B2500
+ @B2501
+ @B2502
+ @B2503
+ @B2504
+ @B2505
+ @B2506
+ @B2507
+ @B2508
+ @B2509
+ @B2510
+ @B2511
+ @B2512
+ @B2513
+ @B2514
+ @B2515
+ @B2516
+ @B2517
+ @B2518
+ @B2519
+ @B2520
+ @B2521
+ @B2522
+ @B2523
+ @B2524
+ @B2525
+ @B2526
+ @B2527
+ @B2528
+ @B2529
+ @B2530
+ @B2531
+ @B2532
+ @B2533
+ @B2534
+ @B2535
+ @B2536
+ @B2537
+ @B2538
+ @B2539
+ @B2540
+ @B2541
+ @B2542
+ @B2543
+ @B2544
+ @B2545
+ @B2546
+ @B2547
+ @B2548
+ @B2549
+ @B2550
+ @B2551
+ @B2552
+ @B2553
+ @B2554
+ @B2555
+ @B2556
+ @B2557
+ @B2558
+ @B2559
+ @B2560
+ @B2561
+ @B2562
+ @B2563
+ @B2564
+ @B2565
+ @B2566
+ @B2567
+ @B2568
+ @B2569
+ @B2570
+ @B2571
+ @B2572
+ @B2573
+ @B2574
+ @B2575
+ @B2576
+ @B2577
+ @B2578
+ @B2579
+ @B2580
+ @B2581
+ @B2582
+ @B2583
+ @B2584
+ @B2585
+ @B2586
+ @B2587
+ @B2588
+ @B2589
+ @B2590
+ @B2591
+ @B2592
+ @B2593
+ @B2594
+ @B2595
+ @B2596
+ @B2597
+ @B2598
+ @B2599
+ @B2600
+ @B2601
+ @B2602
+ @B2603
+ @B2604
+ @B2605
+ @B2606
+ @B2607
+ @B2608
+ @B2609
+ @B2610
+ @B2611
+ @B2612
+ @B2613
+ @B2614
+ @B2615
+ @B2616
+ @B2617
+ @B2618
+ @B2619
+ @B2620
+ @B2621
+ @B2622
+ @B2623
+ @B2624
+ @B2625
+ @B2626
+ @B2627
+ @B2628
+ @B2629
+ @B2630
+ @B2631
+ @B2632
+ @B2633
+ @B2634
+ @B2635
+ @B2636
+ @B2637
+ @B2638
+ @B2639
+ @B2640
+ @B2641
+ @B2642
+ @B2643
+ @B2644
+ @B2645
+ @B2646
+ @B2647
+ @B2648
+ @B2649
+ @B2650
+ @B2651
+ @B2652
+ @B2653
+ @B2654
+ @B2655
+ @B2656
+ @B2657
+ @B2658
+ @B2659
+ @B2660
+ @B2661
+ @B2662
+ @B2663
+ @B2664
+ @B2665
+ @B2666
+ @B2667
+ @B2668
+ @B2669
+ @B2670
+ @B2671
+ @B2672
+ @B2673
+ @B2674
+ @B2675
+ @B2676
+ @B2677
+ @B2678
+ @B2679
+ @B2680
+ @B2681
+ @B2682
+ @B2683
+ @B2684
+ @B2685
+ @B2686
+ @B2687
+ @B2688
+ @B2689
+ @B2690
+ @B2691
+ @B2692
+ @B2693
+ @B2694
+ @B2695
+ @B2696
+ @B2697
+ @B2698
+ @B2699
+ @B2700
+ @B2701
+ @B2702
+ @B2703
+ @B2704
+ @B2705
+ @B2706
+ @B2707
+ @B2708
+ @B2709
+ @B2710
+ @B2711
+ @B2712
+ @B2713
+ @B2714
+ @B2715
+ @B2716
+ @B2717
+ @B2718
+ @B2719
+ @B2720
+ @B2721
+ @B2722
+ @B2723
+ @B2724
+ @B2725
+ @B2726
+ @B2727
+ @B2728
+ @B2729
+ @B2730
+ @B2731
+ @B2732
+ @B2733
+ @B2734
+ @B2735
+ @B2736
+ @B2737
+ @B2738
+ @B2739
+ @B2740
+ @B2741
+ @B2742
+ @B2743
+ @B2744
+ @B2745
+ @B2746
+ @B2747
+ @B2748
+ @B2749
+ @B2750
+ @B2751
+ @B2752
+ @B2753
+ @B2754
+ @B2755
+ @B2756
+ @B2757
+ @B2758
+ @B2759
+ @B2760
+ @B2761
+ @B2762
+ @B2763
+ @B2764
+ @B2765
+ @B2766
+ @B2767
+ @B2768
+ @B2769
+ @B2770
+ @B2771
+ @B2772
+ @B2773
+ @B2774
+ @B2775
+ @B2776
+ @B2777
+ @B2778
+ @B2779
+ @B2780
+ @B2781
+ @B2782
+ @B2783
+ @B2784
+ @B2785
+ @B2786
+ @B2787
+ @B2788
+ @B2789
+ @B2790
+ @B2791
+ @B2792
+ @B2793
+ @B2794
+ @B2795
+ @B2796
+ @B2797
+ @B2798
+ @B2799
+ @B2800
+ @B2801
+ @B2802
+ @B2803
+ @B2804
+ @B2805
+ @B2806
+ @B2807
+ @B2808
+ @B2809
+ @B2810
+ @B2811
+ @B2812
+ @B2813
+ @B2814
+ @B2815
+ @B2816
+ @B2817
+ @B2818
+ @B2819
+ @B2820
+ @B2821
+ @B2822
+ @B2823
+ @B2824
+ @B2825
+ @B2826
+ @B2827
+ @B2828
+ @B2829
+ @B2830
+ @B2831
+ @B2832
+ @B2833
+ @B2834
+ @B2835
+ @B2836
+ @B2837
+ @B2838
+ @B2839
+ @B2840
+ @B2841
+ @B2842
+ @B2843
+ @B2844
+ @B2845
+ @B2846
+ @B2847
+ @B2848
+ @B2849
+ @B2850
+ @B2851
+ @B2852
+ @B2853
+ @B2854
+ @B2855
+ @B2856
+ @B2857
+ @B2858
+ @B2859
+ @B2860
+ @B2861
+ @B2862
+ @B2863
+ @B2864
+ @B2865
+ @B2866
+ @B2867
+ @B2868
+ @B2869
+ @B2870
+ @B2871
+ @B2872
+ @B2873
+ @B2874
+ @B2875
+ @B2876
+ @B2877
+ @B2878
+ @B2879
+ @B2880
+ @B2881
+ @B2882
+ @B2883
+ @B2884
+ @B2885
+ @B2886
+ @B2887
+ @B2888
+ @B2889
+ @B2890
+ @B2891
+ @B2892
+ @B2893
+ @B2894
+ @B2895
+ @B2896
+ @B2897
+ @B2898
+ @B2899
+ @B2900
+ @B2901
+ @B2902
+ @B2903
+ @B2904
+ @B2905
+ @B2906
+ @B2907
+ @B2908
+ @B2909
+ @B2910
+ @B2911
+ @B2912
+ @B2913
+ @B2914
+ @B2915
+ @B2916
+ @B2917
+ @B2918
+ @B2919
+ @B2920
+ @B2921
+ @B2922
+ @B2923
+ @B2924
+ @B2925
+ @B2926
+ @B2927
+ @B2928
+ @B2929
+ @B2930
+ @B2931
+ @B2932
+ @B2933
+ @B2934
+ @B2935
+ @B2936
+ @B2937
+ @B2938
+ @B2939
+ @B2940
+ @B2941
+ @B2942
+ @B2943
+ @B2944
+ @B2945
+ @B2946
+ @B2947
+ @B2948
+ @B2949
+ @B2950
+ @B2951
+ @B2952
+ @B2953
+ @B2954
+ @B2955
+ @B2956
+ @B2957
+ @B2958
+ @B2959
+ @B2960
+ @B2961
+ @B2962
+ @B2963
+ @B2964
+ @B2965
+ @B2966
+ @B2967
+ @B2968
+ @B2969
+ @B2970
+ @B2971
+ @B2972
+ @B2973
+ @B2974
+ @B2975
+ @B2976
+ @B2977
+ @B2978
+ @B2979
+ @B2980
+ @B2981
+ @B2982
+ @B2983
+ @B2984
+ @B2985
+ @B2986
+ @B2987
+ @B2988
+ @B2989
+ @B2990
+ @B2991
+ @B2992
+ @B2993
+ @B2994
+ @B2995
+ @B2996
+ @B2997
+ @B2998
+ @B2999
+ class B {}
+}
diff --git a/luni/src/test/java/libcore/java/math/BigDecimalTest.java b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
index e9c2b0c..d307b14 100644
--- a/luni/src/test/java/libcore/java/math/BigDecimalTest.java
+++ b/luni/src/test/java/libcore/java/math/BigDecimalTest.java
@@ -88,4 +88,12 @@
assertEquals(0, a.subtract(b).signum());
assertEquals(0, a.compareTo(b));
}
+
+ // https://code.google.com/p/android/issues/detail?id=54580
+ public void test54580() {
+ BigDecimal a = new BigDecimal("1.200002");
+ assertEquals("1.200002", a.toPlainString());
+ assertEquals("1.20", a.abs(new MathContext(3,RoundingMode.HALF_UP)).toPlainString());
+ assertEquals("1.200002", a.toPlainString());
+ }
}
diff --git a/luni/src/test/java/libcore/java/math/BigIntegerTest.java b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
index b3cf93f..15a0dad 100644
--- a/luni/src/test/java/libcore/java/math/BigIntegerTest.java
+++ b/luni/src/test/java/libcore/java/math/BigIntegerTest.java
@@ -17,6 +17,7 @@
package libcore.java.math;
import java.math.BigInteger;
+import java.util.Random;
public class BigIntegerTest extends junit.framework.TestCase {
// http://code.google.com/p/android/issues/detail?id=18452
@@ -83,4 +84,76 @@
} catch (NumberFormatException expected) {
}
}
+
+ public void test_Constructor_ILjava_util_Random() throws Exception {
+ Random rand = new Random();
+ BigInteger b;
+ for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+ b = new BigInteger(128, rand);
+ assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 128);
+
+ b = new BigInteger(16, rand);
+ assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 16);
+
+ b = new BigInteger(5, rand);
+ assertTrue(b.toString() + " " + b.bitLength(), b.bitLength() <= 5);
+ }
+ }
+
+ public void test_Constructor_IILjava_util_Random() throws Exception {
+ Random rand = new Random();
+ BigInteger b;
+ for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+ b = new BigInteger(128, 100, rand);
+ assertEquals(b.toString(), 128, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+
+ b = new BigInteger(16, 100, rand);
+ assertEquals(b.toString(), 16, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+
+ b = new BigInteger(5, 100, rand);
+ assertEquals(b.toString(), 5, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+ }
+
+ // Two bits is an interesting special case because there's an even 2-bit prime.
+ int[] primes = new int[1024];
+ boolean saw2 = false;
+ boolean saw3 = false;
+ for (int rep = 0; rep < primes.length; ++rep) { // Manual flakiness protection for random tests.
+ b = new BigInteger(2, 100, rand);
+ assertEquals(b.toString(), 2, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+ primes[rep] = b.intValue();
+ }
+ for (int i = 0; i < primes.length; ++i) {
+ if (primes[i] == 2) {
+ saw2 = true;
+ } else if (primes[i] == 3) {
+ saw3 = true;
+ } else {
+ fail();
+ }
+ }
+ assertTrue(saw2 && saw3);
+ }
+
+ public void test_probablePrime() throws Exception {
+ Random rand = new Random();
+ BigInteger b;
+ for (int rep = 0; rep < 1024; ++rep) { // Manual flakiness protection for random tests.
+ b = BigInteger.probablePrime(128, rand);
+ assertEquals(b.toString(), 128, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+
+ b = BigInteger.probablePrime(16, rand);
+ assertEquals(b.toString(), 16, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+
+ b = BigInteger.probablePrime(5, rand);
+ assertEquals(b.toString(), 5, b.bitLength());
+ assertTrue(b.isProbablePrime(100));
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java b/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
index 8d79027..108fd35 100644
--- a/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
+++ b/luni/src/test/java/libcore/java/net/OldAndroidDatagramTest.java
@@ -20,7 +20,9 @@
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
+import java.nio.channels.DatagramChannel;
import junit.framework.TestCase;
/**
@@ -36,7 +38,7 @@
*/
class Reflector extends Thread {
- // Helper class for reflecting incoming datagrams.
+ // Helper class for reflecting incoming datagrams.
DatagramSocket socket;
boolean alive = true;
@@ -185,4 +187,23 @@
}
}
}
+
+ public void test_54072_DatagramSocket() throws Exception {
+ DatagramSocket s = new DatagramSocket(null);
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
+ s.bind(new InetSocketAddress(8888));
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
+ s.close();
+ assertNull(s.getLocalAddress());
+ }
+
+ public void test_54072_DatagramChannel() throws Exception {
+ DatagramChannel ch = DatagramChannel.open();
+ DatagramSocket s = ch.socket();
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
+ s.bind(new InetSocketAddress(8888));
+ assertTrue(s.getLocalAddress().isAnyLocalAddress());
+ s.close();
+ assertNull(s.getLocalAddress());
+ }
}
diff --git a/luni/src/test/java/libcore/java/net/URLConnectionTest.java b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
index 1f2ebf9..d39e39f 100644
--- a/luni/src/test/java/libcore/java/net/URLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/URLConnectionTest.java
@@ -16,14 +16,11 @@
package libcore.java.net;
+import com.android.okhttp.HttpResponseCache;
import com.google.mockwebserver.MockResponse;
import com.google.mockwebserver.MockWebServer;
import com.google.mockwebserver.RecordedRequest;
import com.google.mockwebserver.SocketPolicy;
-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;
-import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
import dalvik.system.CloseGuard;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -49,21 +46,15 @@
import java.net.UnknownHostException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import java.util.TimeZone;
import java.util.UUID;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.GZIPInputStream;
@@ -81,16 +72,21 @@
import libcore.java.lang.ref.FinalizationTester;
import libcore.java.security.TestKeyStore;
import libcore.javax.net.ssl.TestSSLContext;
-import libcore.net.http.HttpResponseCache;
import tests.net.StuckServer;
+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;
+import static com.google.mockwebserver.SocketPolicy.SHUTDOWN_OUTPUT_AT_END;
+
public final class URLConnectionTest extends TestCase {
- private MockWebServer server = new MockWebServer();
+ private MockWebServer server;
private HttpResponseCache cache;
private String hostName;
@Override protected void setUp() throws Exception {
super.setUp();
+ server = new MockWebServer();
hostName = server.getHostName();
}
@@ -105,7 +101,7 @@
System.clearProperty("https.proxyPort");
server.shutdown();
if (cache != null) {
- cache.getCache().delete();
+ cache.delete();
}
super.tearDown();
}
@@ -1840,7 +1836,6 @@
}
public void testGetKeepAlive() throws Exception {
- MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("ABC"));
server.play();
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 4fc70c4..ec20c2a 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -18,6 +18,7 @@
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
+import java.nio.ByteBuffer;
import java.nio.channels.NoConnectionPendingException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
@@ -129,16 +130,44 @@
}
}
- /**
- * We previously leaked a file descriptor for each selector instance created.
- *
- * http://code.google.com/p/android/issues/detail?id=5993
- * http://code.google.com/p/android/issues/detail?id=4825
- */
+ // We previously leaked a file descriptor for each selector instance created.
+ //
+ // http://code.google.com/p/android/issues/detail?id=5993
+ // http://code.google.com/p/android/issues/detail?id=4825
public void testLeakingPipes() throws IOException {
for (int i = 0; i < 2000; i++) {
Selector selector = Selector.open();
selector.close();
}
}
+
+ public void test_57456() throws Exception {
+ Selector selector = Selector.open();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+
+ try {
+ // Connect.
+ ssc.configureBlocking(false);
+ ssc.socket().bind(null);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(ssc.socket().getLocalSocketAddress());
+ sc.finishConnect();
+
+ // Switch to non-blocking so we can use a Selector.
+ sc.configureBlocking(false);
+
+ // Have the 'server' write something.
+ ssc.accept().write(ByteBuffer.allocate(128));
+
+ // At this point, the client should be able to read or write immediately.
+ // (It shouldn't be able to connect because it's already connected.)
+ SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ assertEquals(1, selector.select());
+ assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps());
+ assertEquals(0, selector.select());
+ } finally {
+ selector.close();
+ ssc.close();
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
index 3ece306..6ab91ab 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
@@ -16,30 +16,69 @@
package libcore.java.nio.channels;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.Selector;
+import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
+import tests.io.MockOs;
+import static libcore.io.OsConstants.*;
public class SocketChannelTest extends junit.framework.TestCase {
- public void test_read_intoReadOnlyByteArrays() throws Exception {
- ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
- ServerSocket ss = new ServerSocket(0);
- ss.setReuseAddress(true);
- SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
- try {
- sc.read(readOnly);
- fail();
- } catch (IllegalArgumentException expected) {
- }
- try {
- sc.read(new ByteBuffer[] { readOnly });
- fail();
- } catch (IllegalArgumentException expected) {
- }
- try {
- sc.read(new ByteBuffer[] { readOnly }, 0, 1);
- fail();
- } catch (IllegalArgumentException expected) {
- }
+ private final MockOs mockOs = new MockOs();
+
+ @Override public void setUp() throws Exception {
+ mockOs.install();
+ }
+
+ @Override protected void tearDown() throws Exception {
+ mockOs.uninstall();
+ }
+
+ public void test_read_intoReadOnlyByteArrays() throws Exception {
+ ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
+ ServerSocket ss = new ServerSocket(0);
+ ss.setReuseAddress(true);
+ SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+ try {
+ sc.read(readOnly);
+ fail();
+ } catch (IllegalArgumentException expected) {
}
+ try {
+ sc.read(new ByteBuffer[] { readOnly });
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ try {
+ sc.read(new ByteBuffer[] { readOnly }, 0, 1);
+ fail();
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void test_56684() throws Exception {
+ mockOs.enqueueFault("connect", ENETUNREACH);
+
+ SocketChannel sc = SocketChannel.open();
+ sc.configureBlocking(false);
+
+ Selector selector = Selector.open();
+ SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
+
+ try {
+ sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] { 0, 0, 0, 0 }), 0));
+ fail();
+ } catch (ConnectException ex) {
+ }
+
+ try {
+ sc.finishConnect();
+ } catch (ClosedChannelException expected) {
+ }
+ }
}
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
index d733a9f..ff510e0 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetEncoderTest.java
@@ -86,20 +86,23 @@
assertEquals(1, cr.length());
}
- public void testCharsetEncoderSurrogatesBrokenByDesign_IGNORE_RI() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.IGNORE);
+ public void testCharsetEncoderSplitSurrogates_IGNORE() throws Exception {
+ testCharsetEncoderSplitSurrogates(CodingErrorAction.IGNORE);
}
- public void testCharsetEncoderSurrogatesBrokenByDesign_REPORT_RI() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.REPORT);
+ public void testCharsetEncoderSplitSurrogates_REPORT() throws Exception {
+ testCharsetEncoderSplitSurrogates(CodingErrorAction.REPORT);
}
- public void testCharsetEncoderSurrogatesBrokenByDesign_REPLACE_RI() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction.REPLACE);
+ public void testCharsetEncoderSplitSurrogates_REPLACE() throws Exception {
+ testCharsetEncoderSplitSurrogates(CodingErrorAction.REPLACE);
}
- private void testCharsetEncoderSurrogatesBrokenByDesign_RI(CodingErrorAction cea) throws Exception {
- // stupid: on the RI, writing the two halves of the surrogate pair in separate writes
+ private void testCharsetEncoderSplitSurrogates(CodingErrorAction cea) throws Exception {
+ // Writing the two halves of the surrogate pair in separate writes should work just fine.
+ // This is true of Android and ICU, but not of the RI.
+
+ // On the RI, writing the two halves of the surrogate pair in separate writes
// is an error because the CharsetEncoder doesn't remember it's half-way through a
// surrogate pair across the two calls!
@@ -108,55 +111,8 @@
// replacement character U+fffd when it sees the second character (because it too
// doesn't remember seeing the first).
- Charset cs = Charset.forName("UTF-32BE");
- CharsetEncoder e = cs.newEncoder();
- e.onMalformedInput(cea);
- e.onUnmappableCharacter(cea);
- ByteBuffer bb = ByteBuffer.allocate(128);
- CoderResult cr = e.encode(CharBuffer.wrap(new char[] { '\ud842' }), bb, false);
- assertEquals(CoderResult.UNDERFLOW, cr);
- assertEquals(0, bb.position());
- cr = e.encode(CharBuffer.wrap(new char[] { '\udf9f' }), bb, false);
- if (cea == CodingErrorAction.REPORT) {
- assertTrue(cr.toString(), cr.isMalformed());
- assertEquals(1, cr.length());
- return;
- }
- assertEquals(CoderResult.UNDERFLOW, cr);
- int expectedPosition = 0;
- if (cea == CodingErrorAction.REPLACE) {
- expectedPosition = 4;
- assertEquals(expectedPosition, bb.position());
- System.err.println(Arrays.toString(Arrays.copyOfRange(bb.array(), 0, bb.position())));
- assertEquals((byte) 0x00, bb.get(0));
- assertEquals((byte) 0x00, bb.get(1));
- assertEquals((byte) 0xff, bb.get(2));
- assertEquals((byte) 0xfd, bb.get(3));
- }
- assertEquals(expectedPosition, bb.position());
- cr = e.encode(CharBuffer.wrap(new char[] { }), bb, true);
- assertEquals(CoderResult.UNDERFLOW, cr);
- assertEquals(expectedPosition, bb.position());
- cr = e.flush(bb);
- assertEquals(CoderResult.UNDERFLOW, cr);
- assertEquals(expectedPosition, bb.position());
- }
+ // Android just does the right thing.
- public void testCharsetEncoderSurrogatesBrokenByDesign_IGNORE() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.IGNORE);
- }
-
- public void testCharsetEncoderSurrogatesBrokenByDesign_REPORT() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.REPORT);
- }
-
- public void testCharsetEncoderSurrogatesBrokenByDesign_REPLACE() throws Exception {
- testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction.REPLACE);
- }
-
- private void testCharsetEncoderSurrogatesBrokenByDesign(CodingErrorAction cea) throws Exception {
- // Writing the two halves of the surrogate pair in separate writes works just fine.
- // This is true of Android and ICU, but not of the RI.
Charset cs = Charset.forName("UTF-32BE");
CharsetEncoder e = cs.newEncoder();
e.onMalformedInput(cea);
@@ -191,8 +147,9 @@
assertEquals(4, bb.position());
try {
cr = e.flush(bb);
+ fail();
} catch (IllegalStateException expected) {
- // you must call encode with endOfInput true before you can flush.
+ // You must call encode with endOfInput true before you can flush.
}
// We had a bug where we wouldn't reset inEnd before calling encode in implFlush.
diff --git a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
index 24daa52..ddc2b29 100644
--- a/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
+++ b/luni/src/test/java/libcore/java/nio/charset/CharsetTest.java
@@ -199,17 +199,6 @@
assertDecodes(cs, "a\u0666", 'a', 0, 0, 0, 0x66, 0x06, 0, 0);
}
- public void test_preNioAliases() throws Exception {
- // Various pre-nio java.lang/java.io encoding names are translated to nio charsets.
- assertEquals("UTF-16BE", Charset.forName("UnicodeBigUnmarked").name());
- assertEquals("UTF-16LE", Charset.forName("UnicodeLittleUnmarked").name());
- assertEquals("UTF-16", Charset.forName("Unicode").name());
- assertEquals("UTF-16", Charset.forName("UnicodeBig").name());
- assertEquals("x-UTF-16LE-BOM", Charset.forName("UnicodeLittle").name());
- assertEquals("X-UTF-32BE-BOM", Charset.forName("UTF_32BE_BOM").name());
- assertEquals("X-UTF-32LE-BOM", Charset.forName("UTF_32LE_BOM").name());
- }
-
private byte[] toByteArray(int[] ints) {
byte[] result = new byte[ints.length];
for (int i = 0; i < ints.length; ++i) {
diff --git a/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java b/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
index b189382..49c5f23 100644
--- a/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
+++ b/luni/src/test/java/libcore/java/nio/charset/Charset_TestGenerator.java
@@ -204,8 +204,7 @@
@Override
void consume (int code) {
- System.out.print(code);
- System.out.print(", ");
+ System.out.printf("0x%x, ", code);
col++;
if (col == colMax) {
System.out.println();
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 d6a635e..411727e 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
@@ -43,13 +43,13 @@
static char[] testChars;
static byte[] testBytes;
- static char[] theseChars (int[] codes) {
+ static char[] theseChars (int... codes) {
char[] chars = new char[codes.length];
for (int i = 0; i < codes.length; i++) chars[i] = (char) codes[i];
return chars;
}
- static byte[] theseBytes (int[] codes) {
+ static byte[] theseBytes (int... codes) {
byte[] bytes = new byte[codes.length];
for (int i = 0; i < codes.length; i++) bytes[i] = (byte) codes[i];
return bytes;
@@ -102,7 +102,7 @@
public void test_dumpEncoded () throws CharacterCodingException {
if (testChars == null) return;
if (testChars.length == 0) return;
- if (testBytes.length > 0) return;
+ if (testBytes != null) return;
System.out.format("\ntest_dumpEncoded() for name %s => %s (class = %s)\n",
charsetName, charset.name(), getClass().getName());
Charset_TestGenerator.Dumper out = new Charset_TestGenerator.Dumper1();
@@ -122,30 +122,10 @@
static void decode (byte[] input, char[] expectedOutput) throws CharacterCodingException {
ByteBuffer inputBB = ByteBuffer.wrap(input);
- CharBuffer outputCB;
decoder.onMalformedInput(CodingErrorAction.REPORT);
- outputCB = decoder.decode(inputBB);
+ CharBuffer outputCB = decoder.decode(inputBB);
outputCB.rewind();
-
-// assertTrue("Decoded charactes must match!",
-// Arrays.equals(expectedOutput, outputCB.array()));
- assertEqualChars("Decoded charactes must match!",
- expectedOutput, outputCB);
-
-// assertEqualChars2("Decoded charactes must match!",
-// expectedOutput,
-// outputCB.array(),
-// input);
-// assertTrue("Decoded charactes (REPLACEed ones INCLUSIVE) must match!",
-// Arrays.equals(expectedOutput, outputCB.array()));
-
-// assertEqualChars("Decoded charactes (REPLACEed ones INCLUSIVE) must match!",
-// expectedOutput,
-// outputCB.array());
-
-// assertEquals("Decoded charactes must match!",
-// String.valueOf(allChars),
-// outputCB.toString());
+ assertEqualChars(expectedOutput, outputCB);
}
public void test_Decode () throws CharacterCodingException {
@@ -241,32 +221,16 @@
// assertTrue(msg, Arrays.equals(actual, expected));
}
- static void assertEqualChars (String msg, char[] expected, CharBuffer actualCB) {
- boolean match = true;
- boolean lenMatch = true;
- char actual;
- int len = actualCB.length();
- if (expected.length != len) {
- lenMatch = false;
- if (expected.length < len) len = expected.length;
- }
- for (int i = 0; i < len; i++) {
- actual = actualCB.get();
+ static void assertEqualChars(char[] expected, CharBuffer actualCB) {
+ assertEquals(expected.length, actualCB.length());
+ for (int i = 0; i < actualCB.length(); ++i) {
+ char actual = actualCB.get();
if (actual != expected[i]) {
- String detail = String.format(
- "Mismatch at index %d: %d instead of expected %d.\n",
- i, (int) actual, (int) expected[i]);
- match = false;
- fail(msg + ": " + detail);
+ String detail = String.format("Mismatch at index %d: %d instead of expected %d.\n",
+ i, (int) actual, (int) expected[i]);
+ fail(detail);
}
-// else {
-// System.out.format("Match index %d: %d = %d\n",
-// i, (int) actual[i], (int) expected[i]);
-// }
}
- assertTrue(msg, match);
- assertTrue(msg + "(IN LENGTH ALSO!)", lenMatch);
-// assertTrue(msg, Arrays.equals(actual, expected));
}
static void assertEqualBytes (String msg, byte[] expected, ByteBuffer actualBB) {
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
index 2e7fcc2..4849ad3 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP.java
@@ -20,506 +20,32 @@
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
-/** @hide
- * SEE correspondig_Android test class:
- */
-
public class OldCharset_MultiByte_EUC_JP extends OldCharset_AbstractTest {
+ @Override protected void setUp() throws Exception {
+ charsetName = "EUC-JP";
+ testChars = "東京 とうきょう トウキョウ Tokyo 123".toCharArray();
+ testBytes = theseBytes(0xc5, 0xec, 0xb5, 0xfe, ' ',
+ 0xa4, 0xc8, 0xa4, 0xa6, 0xa4, 0xad, 0xa4, 0xe7, 0xa4, 0xa6, ' ',
+ 0xa5, 0xc8, 0xa5, 0xa6, 0xa5, 0xad, 0xa5, 0xe7, 0xa5, 0xa6, ' ',
+ 'T', 'o', 'k', 'y', 'o', ' ', '1', '2', '3');
+ super.setUp();
+ }
- protected void setUp() throws Exception {
- charsetName = "EUC-JP";
-
- 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,
-161, 162, 163, 164, /*165,*/ 166, 167, 168, 169, 170, 172, 174, 175, 176, 177, 180,
-182, 184, 186, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
-204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
-221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
-237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
-253, 254, 255, 256, 266, 278, 288, 298, 308, 318, 328, 338, 348, 358, 368, 378,
-461, 471, 501, 711, 728, 900, 910, 920, 931, 941, 951, 961, 971, 1025, 1035, 1045,
-1055, 1065, 1075, 1085, 1095, 1105, 1115, 8208, 8220, 8230, 8240, 8251, 8451, 8470, 8482, 8592,
-8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472, 9484, 9495, 9507,
-9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298, 12308, 12353, 12363,
-12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493, 12503, 12513, 12523,
-12533, 19968, 19978, 19988, 19998, 20008, 20018, 20028, 20039, 20049, 20060, 20072, 20083, 20094, 20104, 20114,
-20124, 20134, 20144, 20154, 20164, 20174, 20184, 20194, 20205, 20215, 20225, 20235, 20245, 20270, 20280, 20290,
-20300, 20310, 20320, 20330, 20341, 20351, 20361, 20371, 20381, 20395, 20405, 20415, 20425, 20436, 20447, 20462,
-20472, 20484, 20494, 20504, 20514, 20524, 20534, 20544, 20554, 20565, 20575, 20586, 20596, 20608, 20618, 20628,
-20638, 20650, 20660, 20670, 20681, 20691, 20701, 20711, 20721, 20731, 20742, 20752, 20762, 20775, 20785, 20795,
-20805, 20815, 20826, 20836, 20846, 20856, 20866, 20876, 20886, 20896, 20906, 20916, 20926, 20936, 20946, 20956,
-20966, 20976, 20986, 20996, 21006, 21016, 21026, 21038, 21048, 21059, 21069, 21079, 21089, 21102, 21112, 21122,
-21132, 21142, 21152, 21162, 21172, 21182, 21192, 21202, 21212, 21222, 21232, 21242, 21253, 21263, 21273, 21283,
-21293, 21304, 21314, 21324, 21335, 21345, 21356, 21367, 21378, 21390, 21400, 21412, 21422, 21432, 21442, 21452,
-21462, 21472, 21482, 21493, 21505, 21515, 21530, 21542, 21553, 21563, 21574, 21585, 21598, 21608, 21619, 21629,
-21640, 21650, 21660, 21670, 21681, 21691, 21702, 21720, 21730, 21740, 21750, 21760, 21772, 21782, 21802, 21813,
-21824, 21834, 21846, 21856, 21883, 21894, 21905, 21916, 21927, 21938, 21951, 21961, 21971, 21982, 21993, 22006,
-22021, 22031, 22041, 22057, 22067, 22077, 22089, 22100, 22110, 22120, 22130, 22144, 22154, 22164, 22174, 22184,
-22195, 22206, 22216, 22227, 22237, 22247, 22257, 22269, 22279, 22289, 22299, 22309, 22319, 22331, 22341, 22351,
-22369, 22379, 22389, 22399, 22409, 22419, 22429, 22439, 22451, 22461, 22471, 22482, 22492, 22502, 22512, 22522,
-22532, 22549, 22559, 22570, 22580, 22591, 22601, 22612, 22622, 22632, 22642, 22652, 22663, 22675, 22685, 22696,
-22706, 22716, 22727, 22737, 22748, 22761, 22771, 22781, 22793, 22803, 22813, 22823, 22833, 22846, 22856, 22866,
-22877, 22887, 22898, 22908, 22922, 22933, 22943, 22956, 22967, 22977, 22987, 23001, 23011, 23022, 23035, 23049,
-23059, 23070, 23080, 23093, 23104, 23116, 23130, 23141, 23159, 23179, 23190, 23200, 23212, 23224, 23234, 23244,
-23254, 23264, 23274, 23285, 23296, 23307, 23318, 23329, 23340, 23350, 23360, 23371, 23381, 23391, 23401, 23411,
-23421, 23431, 23441, 23451, 23461, 23471, 23481, 23491, 23501, 23511, 23521, 23531, 23541, 23551, 23561, 23571,
-23582, 23592, 23602, 23612, 23622, 23632, 23642, 23652, 23662, 23673, 23687, 23697, 23709, 23720, 23730, 23740,
-23751, 23762, 23773, 23784, 23794, 23805, 23815, 23825, 23835, 23846, 23857, 23869, 23880, 23890, 23900, 23913,
-23923, 23934, 23944, 23954, 23965, 23975, 23986, 23996, 24007, 24018, 24029, 24039, 24049, 24059, 24070, 24081,
-24091, 24101, 24111, 24125, 24135, 24145, 24155, 24168, 24178, 24188, 24199, 24213, 24224, 24234, 24245, 24255,
-24265, 24275, 24285, 24296, 24307, 24318, 24328, 24339, 24349, 24359, 24369, 24379, 24389, 24400, 24411, 24422,
-24432, 24442, 24452, 24463, 24473, 24484, 24494, 24504, 24515, 24525, 24535, 24545, 24555, 24565, 24575, 24586,
-24596, 24607, 24617, 24627, 24640, 24650, 24660, 24671, 24681, 24693, 24703, 24713, 24723, 24733, 24743, 24753,
-24763, 24773, 24783, 24793, 24803, 24816, 24826, 24838, 24848, 24858, 24871, 24881, 24892, 24902, 24915, 24925,
-24935, 24945, 24955, 24967, 24977, 24988, 24999, 25010, 25020, 25030, 25040, 25052, 25062, 25074, 25084, 25095,
-25105, 25115, 25126, 25136, 25147, 25158, 25168, 25178, 25188, 25198, 25209, 25219, 25229, 25239, 25254, 25265,
-25275, 25285, 25295, 25305, 25322, 25332, 25342, 25352, 25363, 25375, 25385, 25397, 25407, 25417, 25427, 25445,
-25457, 25467, 25479, 25490, 25502, 25512, 25522, 25533, 25544, 25554, 25564, 25577, 25587, 25606, 25616, 25628,
-25638, 25648, 25658, 25675, 25688, 25699, 25709, 25720, 25731, 25743, 25753, 25763, 25773, 25785, 25796, 25806,
-25816, 25826, 25836, 25846, 25856, 25866, 25876, 25886, 25897, 25908, 25918, 25928, 25938, 25949, 25959, 25970,
-25981, 25991, 26001, 26011, 26021, 26031, 26041, 26051, 26062, 26072, 26082, 26092, 26105, 26115, 26125, 26140,
-26150, 26160, 26172, 26182, 26193, 26203, 26214, 26224, 26234, 26244, 26254, 26264, 26274, 26285, 26296, 26306,
-26316, 26326, 26336, 26347, 26357, 26367, 26377, 26387, 26397, 26407, 26417, 26429, 26439, 26449, 26460, 26470,
-26480, 26491, 26501, 26511, 26521, 26534, 26544, 26555, 26565, 26575, 26585, 26596, 26606, 26617, 26627, 26643,
-26653, 26663, 26673, 26683, 26693, 26704, 26715, 26727, 26737, 26747, 26757, 26767, 26778, 26789, 26799, 26809,
-26820, 26831, 26841, 26851, 26861, 26873, 26884, 26894, 26905, 26915, 26928, 26939, 26949, 26963, 26973, 26984,
-26994, 27004, 27018, 27028, 27040, 27051, 27063, 27073, 27083, 27094, 27106, 27117, 27129, 27139, 27151, 27161,
-27171, 27182, 27192, 27204, 27214, 27224, 27234, 27249, 27262, 27273, 27287, 27298, 27308, 27320, 27330, 27340,
-27350, 27364, 27376, 27386, 27396, 27407, 27419, 27431, 27442, 27453, 27463, 27474, 27485, 27495, 27507, 27517,
-27529, 27541, 27551, 27561, 27571, 27581, 27593, 27603, 27615, 27627, 27639, 27650, 27661, 27671, 27683, 27694,
-27704, 27714, 27725, 27735, 27746, 27757, 27768, 27778, 27788, 27798, 27809, 27819, 27832, 27842, 27852, 27862,
-27872, 27882, 27892, 27908, 27918, 27929, 27941, 27951, 27961, 27972, 27991, 28001, 28012, 28023, 28034, 28044,
-28054, 28074, 28084, 28095, 28106, 28117, 28127, 28137, 28147, 28160, 28170, 28181, 28191, 28201, 28214, 28227,
-28237, 28247, 28258, 28270, 28283, 28300, 28310, 28320, 28330, 28342, 28352, 28362, 28372, 28382, 28395, 28407,
-28417, 28428, 28438, 28448, 28458, 28470, 28481, 28495, 28505, 28516, 28526, 28536, 28546, 28556, 28566, 28576,
-28586, 28597, 28608, 28618, 28628, 28638, 28648, 28659, 28669, 28679, 28689, 28699, 28710, 28720, 28732, 28744,
-28756, 28766, 28779, 28789, 28801, 28814, 28824, 28836, 28846, 28856, 28872, 28883, 28893, 28913, 28925, 28935,
-28948, 28958, 28971, 28982, 28993, 29003, 29013, 29024, 29036, 29049, 29060, 29071, 29081, 29096, 29106, 29118,
-29128, 29138, 29148, 29158, 29173, 29183, 29193, 29203, 29213, 29224, 29234, 29244, 29254, 29264, 29274, 29287,
-29297, 29307, 29319, 29330, 29344, 29356, 29366, 29377, 29388, 29398, 29408, 29420, 29431, 29442, 29453, 29463,
-29474, 29484, 29494, 29507, 29517, 29527, 29539, 29550, 29560, 29571, 29582, 29592, 29602, 29613, 29623, 29634,
-29644, 29654, 29664, 29674, 29684, 29694, 29705, 29722, 29732, 29742, 29753, 29763, 29773, 29783, 29794, 29805,
-29822, 29833, 29848, 29858, 29870, 29881, 29896, 29907, 29918, 29928, 29938, 29948, 29958, 29969, 29980, 29990,
-30000, 30010, 30020, 30030, 30041, 30052, 30063, 30073, 30085, 30095, 30105, 30115, 30129, 30140, 30150, 30162,
-30172, 30183, 30193, 30204, 30215, 30226, 30236, 30246, 30256, 30266, 30276, 30290, 30300, 30311, 30321, 30331,
-30341, 30352, 30362, 30372, 30382, 30392, 30402, 30412, 30422, 30432, 30442, 30452, 30462, 30472, 30482, 30492,
-30502, 30516, 30526, 30538, 30550, 30560, 30570, 30580, 30590, 30603, 30613, 30623, 30634, 30645, 30655, 30665,
-30677, 30687, 30697, 30707, 30722, 30732, 30749, 30759, 30770, 30783, 30796, 30812, 30824, 30834, 30844, 30854,
-30865, 30877, 30887, 30897, 30907, 30917, 30928, 30938, 30948, 30959, 30970, 30982, 30992, 31002, 31013, 31025,
-31035, 31045, 31055, 31066, 31077, 31090, 31100, 31114, 31124, 31137, 31147, 31160, 31170, 31183, 31194, 31204,
-31216, 31227, 31239, 31249, 31259, 31271, 31281, 31291, 31301, 31311, 31321, 31331, 31341, 31352, 31362, 31376,
-31390, 31401, 31411, 31423, 31433, 31443, 31453, 31464, 31476, 31486, 31496, 31508, 31518, 31528, 31539, 31549,
-31559, 31569, 31581, 31591, 31601, 31620, 31630, 31640, 31653, 31663, 31674, 31684, 31695, 31705, 31716, 31730,
-31740, 31750, 31761, 31771, 31781, 31793, 31805, 31818, 31828, 31838, 31849, 31859, 31869, 31879, 31890, 31902,
-31912, 31922, 31932, 31943, 31954, 31964, 31974, 31986, 31998, 32008, 32018, 32028, 32038, 32048, 32058, 32068,
-32078, 32089, 32099, 32110, 32120, 32130, 32140, 32150, 32162, 32172, 32182, 32194, 32204, 32215, 32225, 32235,
-32245, 32256, 32266, 32277, 32287, 32299, 32309, 32319, 32330, 32340, 32350, 32361, 32371, 32381, 32391, 32401,
-32411, 32566, 32579, 32589, 32600, 32611, 32621, 32631, 32642, 32652, 32662, 32673, 32685, 32696, 32707, 32718,
-32731, 32741, 32751, 32761, 32771, 32781, 32791, 32801, 32812, 32822, 32832, 32842, 32854, 32864, 32877, 32887,
-32897, 32907, 32918, 32929, 32939, 32952, 32963, 32973, 32983, 32993, 33005, 33016, 33026, 33046, 33056, 33068,
-33081, 33093, 33104, 33119, 33129, 33140, 33151, 33162, 33173, 33184, 33198, 33208, 33218, 33229, 33239, 33249,
-33259, 33269, 33279, 33289, 33299, 33309, 33320, 33330, 33344, 33355, 33366, 33376, 33386, 33396, 33406, 33417,
-33428, 33439, 33449, 33459, 33469, 33488, 33498, 33508, 33519, 33529, 33539, 33550, 33560, 33570, 33580, 33590,
-33600, 33610, 33620, 33648, 33659, 33669, 33682, 33692, 33702, 33713, 33725, 33735, 33745, 33756, 33768, 33778,
-33788, 33798, 33809, 33824, 33834, 33845, 33861, 33871, 33881, 33891, 33901, 33911, 33921, 33931, 33941, 33951,
-33961, 33972, 33982, 33992, 34003, 34023, 34033, 34043, 34054, 34064, 34074, 34084, 34095, 34109, 34120, 34130,
-34140, 34152, 34167, 34177, 34187, 34199, 34210, 34220, 34230, 34241, 34251, 34261, 34271, 34281, 34291, 34302,
-34314, 34326, 34337, 34349, 34360, 34370, 34381, 34391, 34401, 34411, 34421, 34440, 34451, 34465, 34475, 34485,
-34495, 34505, 34516, 34526, 34537, 34552, 34562, 34573, 34584, 34595, 34606, 34617, 34627, 34637, 34647, 34657,
-34670, 34680, 34690, 34700, 34711, 34722, 34732, 34746, 34756, 34766, 34777, 34787, 34797, 34807, 34817, 34827,
-34837, 34847, 34861, 34873, 34883, 34893, 34903, 34913, 34923, 34933, 34943, 34955, 34966, 34976, 34986, 34996,
-35006, 35018, 35028, 35038, 35048, 35058, 35068, 35078, 35088, 35098, 35109, 35120, 35130, 35140, 35151, 35162,
-35172, 35182, 35194, 35206, 35216, 35226, 35237, 35247, 35258, 35282, 35292, 35302, 35313, 35325, 35335, 35345,
-35355, 35365, 35375, 35386, 35397, 35408, 35419, 35429, 35440, 35450, 35460, 35471, 35481, 35491, 35501, 35511,
-35522, 35532, 35542, 35552, 35563, 35573, 35583, 35594, 35604, 35614, 35624, 35635, 35646, 35656, 35666, 35676,
-35686, 35696, 35708, 35722, 35732, 35742, 35895, 35905, 35915, 35925, 35937, 35947, 35957, 35970, 35980, 35992,
-36002, 36012, 36022, 36032, 36042, 36053, 36064, 36074, 36085, 36095, 36105, 36115, 36196, 36206, 36223, 36234,
-36245, 36255, 36267, 36277, 36288, 36298, 36308, 36319, 36330, 36340, 36351, 36361, 36372, 36382, 36394, 36404,
-36416, 36426, 36436, 36446, 36457, 36468, 36481, 36491, 36501, 36513, 36523, 36533, 36544, 36554, 36564, 36575,
-36587, 36599, 36610, 36620, 36630, 36640, 36650, 36660, 36670, 36681, 36691, 36701, 36763, 36773, 36783, 36794,
-36804, 36814, 36826, 36836, 36846, 36856, 36866, 36876, 36886, 36896, 36906, 36916, 36926, 36937, 36947, 36957,
-36967, 36978, 36988, 36999, 37009, 37019, 37029, 37039, 37053, 37063, 37074, 37084, 37096, 37108, 37118, 37128,
-37138, 37148, 37159, 37169, 37180, 37191, 37202, 37217, 37228, 37239, 37249, 37259, 37269, 37281, 37291, 37301,
-37311, 37321, 37331, 37341, 37351, 37361, 37371, 37381, 37392, 37404, 37414, 37424, 37434, 37444, 37454, 37464,
-37474, 37486, 37496, 37507, 37517, 37527, 37540, 37551, 37561, 37571, 37581, 37591, 37601, 37612, 37624, 37634,
-37645, 37656, 37666, 37676, 37686, 37700, 37712, 37722, 37732, 37742, 37754, 37768, 37778, 37790, 37800, 37812,
-37825, 37835, 37846, 37857, 37879, 37889, 37901, 37911, 37921, 37931, 37941, 37951, 37962, 37973, 37983, 37994,
-38005, 38015, 38263, 38274, 38284, 38294, 38304, 38315, 38326, 38339, 38349, 38360, 38370, 38428, 38438, 38449,
-38459, 38475, 38486, 38497, 38508, 38518, 38529, 38539, 38549, 38559, 38569, 38579, 38592, 38602, 38613, 38623,
-38633, 38646, 38656, 38666, 38678, 38689, 38704, 38717, 38728, 38738, 38748, 38758, 38769, 38779, 38789, 38799,
-38809, 38819, 38829, 38840, 38851, 38861, 38871, 38881, 38893, 38903, 38913, 38924, 38934, 38944, 38955, 38965,
-38980, 38990, 39000, 39010, 39020, 39080, 39092, 39103, 39116, 39131, 39141, 39151, 39164, 39175, 39185, 39195,
-39206, 39217, 39227, 39237, 39248, 39259, 39318, 39333, 39344, 39354, 39364, 39376, 39386, 39399, 39409, 39419,
-39429, 39439, 39449, 39459, 39469, 39479, 39489, 39499, 39509, 39519, 39529, 39592, 39602, 39612, 39622, 39632,
-39643, 39653, 39663, 39673, 39683, 39693, 39704, 39714, 39725, 39735, 39745, 39755, 39765, 39777, 39787, 39797,
-39807, 39817, 39827, 39837, 39847, 39857, 39867, 39878, 39888, 39899, 39909, 39919, 39929, 39940, 39951, 39961,
-39971, 39981, 39991, 40001, 40014, 40024, 40035, 40046, 40056, 40165, 40176, 40194, 40206, 40216, 40227, 40239,
-40250, 40260, 40272, 40284, 40297, 40310, 40323, 40333, 40343, 40353, 40363, 40373, 40383, 40393, 40403, 40414,
-40425, 40435, 40445, 40455, 40465, 40475, 40565, 40575, 40587, 40597, 40607, 40617, 40627, 40638, 40648, 40658,
-40668, 40679, 40689, 40699, 40711, 40721, 40731, 40742, 40753, 40763, 40773, 40783, 40794, 40806, 40816, 40826,
-40845, 40855, 40865, 65281, 65291, 65301, 65311, 65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401,
-65411, 65421, 65431, 65507
- });
-
- 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,
-143, 162, 194, 161, 241, 161, 242, 143, 162, 240, /*92,*/ 143, 162, 195, 161, 248,
-161, 175, 143, 162, 237, 143, 162, 236, 162, 204, 143, 162, 238, 143, 162, 180,
-161, 235, 161, 222, 161, 173, 162, 249, 143, 162, 177, 143, 162, 235, 143, 162,
-196, 143, 170, 162, 143, 170, 161, 143, 170, 164, 143, 170, 170, 143, 170, 163,
-143, 170, 169, 143, 169, 161, 143, 170, 174, 143, 170, 178, 143, 170, 177, 143,
-170, 180, 143, 170, 179, 143, 170, 192, 143, 170, 191, 143, 170, 194, 143, 170,
-193, 143, 170, 208, 143, 170, 210, 143, 170, 209, 143, 170, 212, 143, 170, 216,
-143, 170, 211, 161, 223, 143, 169, 172, 143, 170, 227, 143, 170, 226, 143, 170,
-229, 143, 170, 228, 143, 170, 242, 143, 169, 176, 143, 169, 206, 143, 171, 162,
-143, 171, 161, 143, 171, 164, 143, 171, 170, 143, 171, 163, 143, 171, 169, 143,
-169, 193, 143, 171, 174, 143, 171, 178, 143, 171, 177, 143, 171, 180, 143, 171,
-179, 143, 171, 192, 143, 171, 191, 143, 171, 194, 143, 171, 193, 143, 169, 195,
-143, 171, 208, 143, 171, 210, 143, 171, 209, 143, 171, 212, 143, 171, 216, 143,
-171, 211, 161, 224, 143, 169, 204, 143, 171, 227, 143, 171, 226, 143, 171, 229,
-143, 171, 228, 143, 171, 242, 143, 169, 208, 143, 171, 243, 143, 170, 167, 143,
-170, 175, 143, 170, 182, 143, 170, 189, 143, 170, 197, 143, 170, 200, 143, 171,
-203, 143, 171, 206, 143, 169, 173, 143, 170, 221, 143, 169, 175, 143, 170, 232,
-143, 171, 245, 143, 170, 166, 143, 170, 237, 143, 171, 185, 143, 162, 176, 143,
-162, 175, 143, 162, 184, 143, 166, 233, 166, 168, 166, 178, 143, 166, 242, 166,
-199, 166, 209, 143, 166, 250, 167, 167, 143, 167, 203, 167, 166, 167, 177, 167,
-187, 167, 212, 167, 223, 167, 233, 167, 215, 143, 167, 251, 161, 190, 161, 200,
-161, 196, 162, 243, 162, 168, 161, 238, 143, 162, 241, 143, 162, 239, 162, 171,
-162, 205, 162, 207, 162, 187, 162, 229, 162, 202, 161, 232, 162, 226, 161, 226,
-162, 227, 162, 190, 162, 221, 162, 222, 168, 161, 168, 163, 168, 177, 168, 178,
-168, 184, 168, 181, 168, 182, 162, 163, 162, 165, 162, 167, 162, 161, 162, 254,
-161, 250, 161, 234, 162, 246, 161, 161, 161, 212, 161, 204, 164, 161, 164, 171,
-164, 181, 164, 191, 164, 201, 164, 211, 164, 221, 164, 231, 164, 241, 161, 171,
-165, 165, 165, 175, 165, 185, 165, 195, 165, 205, 165, 215, 165, 225, 165, 235,
-165, 245, 176, 236, 190, 229, 179, 238, 190, 231, 143, 176, 169, 182, 250, 208,
-167, 143, 176, 178, 143, 176, 179, 143, 176, 181, 143, 176, 183, 198, 253, 180,
-165, 205, 189, 184, 223, 176, 161, 203, 242, 208, 183, 191, 205, 208, 188, 208,
-186, 201, 213, 143, 176, 201, 208, 193, 208, 195, 180, 235, 143, 176, 214, 143,
-176, 217, 143, 176, 221, 191, 173, 143, 176, 231, 143, 176, 235, 143, 176, 238,
-143, 176, 223, 143, 176, 242, 202, 187, 187, 200, 143, 177, 162, 143, 177, 168,
-176, 205, 213, 165, 191, 175, 202, 216, 143, 177, 187, 208, 215, 208, 216, 189,
-164, 202, 240, 143, 177, 203, 143, 177, 207, 143, 177, 211, 143, 177, 216, 208,
-235, 182, 230, 143, 177, 223, 143, 177, 228, 208, 243, 143, 177, 236, 143, 177,
-242, 194, 166, 208, 250, 143, 177, 251, 143, 178, 163, 143, 178, 167, 143, 178,
-172, 208, 253, 183, 185, 209, 161, 143, 178, 185, 143, 178, 189, 193, 206, 143,
-178, 197, 202, 200, 143, 178, 202, 143, 178, 210, 209, 179, 143, 178, 218, 143,
-178, 223, 209, 184, 189, 188, 143, 178, 231, 197, 222, 143, 178, 237, 209, 194,
-197, 181, 209, 196, 209, 198, 209, 204, 180, 167, 209, 209, 186, 227, 143, 178,
-252, 143, 179, 161, 143, 179, 164, 244, 165, 189, 232, 209, 224, 189, 208, 209,
-227, 209, 230, 143, 179, 183, 143, 179, 184, 209, 233, 183, 244, 196, 230, 193,
-176, 143, 179, 193, 143, 179, 199, 143, 179, 201, 143, 179, 203, 143, 179, 206,
-143, 179, 209, 143, 179, 212, 178, 195, 197, 216, 207, 171, 179, 175, 143, 179,
-232, 240, 213, 143, 179, 239, 210, 171, 143, 179, 246, 188, 219, 202, 241, 210,
-183, 186, 252, 210, 186, 143, 180, 175, 210, 190, 143, 180, 182, 143, 180, 183,
-198, 238, 143, 180, 187, 143, 180, 190, 210, 203, 210, 204, 143, 180, 198, 206,
-210, 143, 180, 204, 210, 209, 143, 180, 212, 187, 178, 193, 208, 188, 232, 143,
-180, 224, 194, 254, 143, 180, 227, 210, 222, 177, 165, 143, 180, 230, 200, 221,
-143, 180, 236, 202, 173, 202, 242, 198, 221, 143, 180, 244, 188, 254, 204, 163,
-204, 191, 143, 181, 164, 210, 240, 143, 181, 170, 143, 181, 173, 143, 181, 179,
-143, 181, 183, 143, 181, 185, 211, 166, 211, 175, 143, 181, 191, 143, 181, 193,
-143, 181, 197, 143, 181, 202, 176, 162, 143, 181, 206, 143, 181, 209, 211, 177,
-143, 181, 217, 211, 183, 143, 181, 225, 211, 193, 143, 181, 232, 143, 181, 236,
-180, 238, 183, 246, 143, 181, 244, 143, 181, 245, 143, 181, 249, 143, 182, 161,
-143, 182, 165, 143, 182, 167, 143, 182, 168, 143, 182, 170, 143, 182, 175, 143,
-182, 179, 178, 222, 143, 182, 182, 143, 182, 188, 143, 182, 195, 143, 182, 199,
-143, 182, 200, 180, 239, 143, 182, 210, 211, 230, 211, 231, 211, 233, 143, 182,
-221, 143, 182, 225, 143, 182, 231, 143, 182, 233, 211, 244, 211, 247, 143, 182,
-244, 143, 182, 250, 143, 182, 252, 185, 241, 143, 183, 165, 143, 183, 168, 143,
-183, 171, 143, 183, 177, 143, 183, 182, 212, 173, 143, 183, 188, 212, 175, 212,
-179, 143, 183, 197, 143, 183, 205, 212, 180, 212, 181, 212, 182, 143, 183, 220,
-143, 183, 225, 212, 184, 143, 183, 230, 143, 183, 231, 212, 191, 199, 184, 143,
-183, 239, 143, 183, 243, 180, 240, 143, 183, 251, 194, 196, 143, 184, 165, 180,
-174, 190, 236, 143, 184, 172, 143, 184, 173, 197, 227, 186, 201, 143, 184, 183,
-212, 199, 143, 184, 185, 143, 184, 189, 202, 232, 143, 184, 199, 203, 207, 143,
-184, 206, 143, 184, 208, 195, 197, 212, 219, 212, 224, 143, 184, 221, 143, 184,
-222, 212, 232, 202, 209, 143, 184, 228, 143, 184, 231, 194, 231, 188, 186, 212,
-243, 198, 224, 143, 184, 244, 143, 184, 248, 212, 252, 143, 185, 162, 143, 185,
-167, 199, 165, 143, 185, 172, 143, 185, 174, 197, 202, 143, 185, 182, 143, 185,
-185, 187, 207, 213, 172, 143, 185, 195, 143, 185, 198, 176, 249, 213, 178, 143,
-185, 210, 143, 185, 211, 143, 185, 215, 213, 183, 213, 180, 143, 185, 223, 186,
-167, 143, 185, 228, 143, 185, 231, 143, 185, 235, 143, 185, 238, 143, 185, 243,
-143, 185, 246, 143, 185, 251, 213, 191, 183, 249, 213, 197, 143, 186, 167, 143,
-186, 169, 143, 186, 171, 143, 186, 174, 213, 201, 213, 202, 143, 186, 182, 196,
-220, 213, 206, 213, 210, 143, 186, 187, 213, 212, 204, 210, 213, 216, 213, 218,
-143, 186, 196, 177, 167, 143, 186, 205, 176, 184, 205, 168, 143, 186, 213, 205,
-198, 213, 227, 143, 186, 221, 143, 186, 224, 178, 201, 213, 237, 195, 254, 188,
-247, 176, 211, 213, 245, 143, 186, 235, 213, 248, 143, 186, 244, 198, 244, 213,
-252, 214, 161, 143, 186, 248, 193, 216, 214, 165, 214, 168, 143, 187, 169, 214,
-170, 143, 187, 174, 193, 187, 143, 187, 181, 214, 176, 214, 180, 143, 187, 187,
-143, 187, 188, 178, 229, 143, 187, 192, 214, 183, 191, 242, 214, 194, 214, 193,
-143, 187, 201, 143, 187, 203, 143, 187, 206, 143, 187, 211, 214, 201, 214, 191,
-191, 243, 214, 205, 143, 187, 226, 143, 187, 230, 143, 187, 232, 214, 211, 143,
-187, 240, 143, 230, 244, 214, 217, 143, 187, 247, 214, 221, 192, 238, 185, 170,
-184, 202, 180, 172, 200, 193, 214, 230, 214, 231, 191, 227, 194, 211, 203, 185,
-214, 243, 143, 188, 181, 143, 188, 184, 143, 188, 187, 180, 179, 205, 196, 200,
-223, 196, 236, 214, 249, 143, 188, 201, 176, 195, 143, 188, 207, 206, 247, 179,
-199, 215, 163, 215, 168, 215, 172, 215, 176, 143, 188, 223, 181, 221, 143, 188,
-227, 184, 204, 188, 229, 143, 188, 239, 143, 188, 244, 143, 188, 247, 143, 188,
-250, 201, 167, 190, 180, 143, 189, 166, 183, 194, 143, 189, 171, 215, 208, 143,
-189, 178, 200, 249, 143, 189, 183, 191, 180, 199, 166, 187, 214, 143, 189, 195,
-178, 247, 199, 176, 215, 221, 143, 189, 210, 143, 189, 213, 143, 189, 217, 215,
-226, 143, 189, 220, 143, 189, 222, 215, 240, 143, 189, 228, 215, 239, 178, 184,
-183, 195, 143, 189, 236, 188, 189, 143, 189, 243, 143, 189, 246, 216, 166, 143,
-189, 253, 143, 190, 161, 190, 240, 143, 190, 170, 143, 190, 173, 193, 218, 194,
-198, 216, 185, 216, 180, 143, 190, 188, 182, 242, 216, 195, 143, 190, 202, 216,
-198, 143, 190, 209, 216, 216, 216, 215, 183, 197, 216, 213, 143, 190, 216, 216,
-220, 216, 225, 143, 190, 229, 198, 180, 183, 251, 143, 190, 239, 216, 234, 178,
-251, 143, 190, 246, 216, 239, 196, 168, 216, 246, 143, 191, 167, 178, 230, 216,
-254, 192, 239, 217, 165, 204, 225, 143, 191, 182, 143, 191, 184, 143, 191, 189,
-143, 191, 191, 202, 177, 200, 227, 217, 183, 143, 191, 197, 185, 179, 143, 191,
-201, 202, 250, 217, 187, 195, 180, 217, 188, 192, 219, 143, 191, 214, 143, 191,
-216, 189, 166, 217, 205, 143, 191, 225, 182, 180, 143, 191, 228, 143, 191, 231,
-193, 222, 194, 170, 143, 191, 244, 143, 191, 248, 143, 191, 252, 199, 177, 143,
-192, 167, 199, 211, 143, 192, 174, 191, 228, 183, 199, 143, 192, 180, 143, 192,
-183, 217, 231, 143, 192, 189, 217, 226, 143, 192, 195, 217, 236, 143, 192, 201,
-217, 211, 217, 238, 143, 192, 213, 183, 200, 143, 192, 217, 197, 166, 143, 192,
-230, 143, 192, 231, 204, 206, 183, 226, 143, 192, 238, 143, 192, 242, 143, 192,
-247, 199, 197, 179, 201, 143, 193, 161, 143, 193, 166, 218, 166, 197, 167, 181,
-188, 218, 177, 218, 181, 143, 193, 185, 143, 193, 188, 143, 193, 192, 143, 193,
-196, 218, 189, 202, 252, 218, 195, 143, 193, 206, 218, 201, 143, 193, 210, 218,
-202, 143, 193, 213, 202, 184, 200, 195, 218, 207, 192, 205, 187, 219, 202, 253,
-218, 211, 143, 193, 232, 143, 193, 236, 180, 251, 189, 220, 143, 193, 242, 218,
-224, 143, 193, 249, 218, 230, 143, 194, 166, 143, 194, 172, 195, 235, 143, 194,
-179, 143, 194, 182, 143, 194, 187, 179, 162, 218, 242, 195, 210, 218, 247, 218,
-245, 218, 248, 196, 170, 143, 194, 217, 219, 162, 143, 194, 224, 143, 194, 227,
-219, 163, 219, 165, 143, 194, 234, 219, 170, 194, 216, 205, 173, 143, 194, 241,
-196, 171, 219, 176, 188, 235, 181, 224, 143, 194, 249, 194, 188, 197, 206, 143,
-195, 161, 219, 191, 143, 195, 166, 219, 199, 143, 195, 170, 143, 195, 175, 219,
-197, 143, 195, 177, 143, 195, 181, 143, 195, 188, 199, 240, 143, 195, 193, 219,
-207, 219, 211, 143, 195, 184, 198, 202, 192, 242, 143, 195, 204, 143, 195, 207,
-143, 195, 212, 143, 195, 214, 143, 195, 217, 182, 205, 143, 195, 223, 201, 176,
-143, 195, 228, 143, 195, 233, 199, 223, 219, 231, 143, 195, 241, 143, 195, 245,
-196, 244, 219, 238, 180, 254, 143, 195, 254, 143, 196, 165, 220, 168, 143, 196,
-173, 220, 170, 220, 166, 196, 199, 191, 250, 220, 176, 220, 191, 143, 196, 193,
-143, 196, 195, 201, 246, 220, 194, 143, 196, 204, 143, 196, 209, 207, 176, 186,
-231, 207, 177, 220, 213, 143, 196, 222, 143, 196, 225, 220, 201, 185, 189, 143,
-196, 232, 143, 196, 234, 220, 229, 220, 223, 143, 196, 244, 143, 196, 245, 201,
-184, 220, 235, 220, 211, 220, 247, 220, 237, 143, 197, 170, 181, 204, 220, 243,
-143, 197, 180, 143, 197, 182, 143, 197, 187, 221, 161, 220, 253, 221, 168, 221,
-166, 221, 165, 143, 197, 206, 143, 197, 210, 143, 197, 213, 143, 197, 216, 221,
-178, 205, 243, 143, 197, 226, 143, 197, 230, 178, 164, 205, 223, 182, 214, 221,
-188, 143, 197, 244, 143, 197, 247, 143, 197, 249, 186, 208, 143, 197, 254, 189,
-222, 221, 205, 143, 198, 166, 143, 198, 171, 221, 213, 143, 198, 178, 143, 198,
-182, 221, 218, 221, 219, 221, 221, 143, 198, 192, 143, 198, 195, 143, 198, 199,
-181, 164, 221, 230, 143, 198, 209, 177, 202, 181, 225, 143, 198, 218, 180, 192,
-221, 233, 143, 198, 226, 143, 198, 230, 221, 235, 198, 217, 178, 173, 203, 215,
-203, 247, 202, 168, 143, 198, 246, 200, 231, 143, 198, 254, 143, 199, 163, 222,
-165, 143, 199, 170, 143, 199, 171, 143, 199, 174, 222, 172, 196, 197, 143, 199,
-184, 143, 199, 186, 190, 244, 143, 199, 189, 143, 199, 192, 179, 189, 179, 164,
-143, 199, 198, 205, 176, 143, 199, 203, 143, 199, 206, 143, 199, 208, 143, 199,
-212, 143, 199, 215, 222, 204, 143, 199, 221, 143, 199, 225, 189, 223, 143, 199,
-231, 222, 189, 222, 188, 222, 219, 178, 185, 143, 199, 237, 222, 220, 222, 218,
-143, 199, 251, 143, 200, 161, 222, 208, 143, 200, 165, 200, 174, 189, 224, 143,
-200, 170, 222, 228, 205, 207, 143, 200, 178, 143, 200, 183, 222, 237, 194, 218,
-143, 200, 187, 223, 163, 181, 249, 143, 200, 196, 143, 200, 198, 199, 249, 143,
-200, 204, 143, 200, 208, 222, 243, 143, 200, 212, 143, 200, 217, 189, 225, 196,
-172, 223, 166, 223, 173, 143, 200, 231, 143, 200, 237, 143, 200, 240, 223, 186,
-143, 200, 248, 183, 227, 143, 200, 254, 223, 190, 143, 201, 162, 143, 201, 163,
-223, 171, 143, 201, 169, 143, 201, 173, 223, 198, 223, 202, 195, 245, 223, 208,
-143, 201, 182, 143, 201, 185, 143, 201, 189, 143, 201, 192, 178, 208, 143, 201,
-198, 143, 201, 201, 177, 234, 143, 201, 208, 143, 201, 210, 223, 220, 223, 218,
-206, 245, 143, 201, 218, 223, 223, 223, 216, 223, 226, 143, 201, 230, 177, 235,
-143, 201, 234, 143, 201, 236, 193, 179, 143, 201, 242, 143, 201, 247, 223, 230,
-143, 201, 254, 223, 236, 143, 202, 162, 223, 239, 223, 237, 244, 166, 223, 241,
-143, 202, 174, 223, 245, 197, 245, 223, 246, 143, 202, 187, 187, 184, 223, 253,
-224, 162, 143, 202, 193, 143, 202, 194, 143, 202, 197, 224, 166, 224, 170, 224,
-172, 224, 175, 143, 202, 211, 143, 202, 215, 203, 210, 143, 202, 224, 143, 202,
-227, 224, 182, 224, 183, 181, 190, 184, 164, 190, 245, 143, 202, 242, 143, 202,
-245, 143, 202, 247, 224, 195, 198, 200, 224, 198, 143, 203, 162, 143, 203, 167,
-224, 200, 143, 203, 173, 143, 203, 177, 205, 177, 143, 203, 184, 143, 203, 185,
-224, 213, 189, 195, 143, 203, 199, 224, 217, 143, 203, 207, 143, 203, 210, 143,
-203, 215, 143, 203, 220, 143, 203, 225, 143, 203, 227, 178, 209, 143, 203, 236,
-143, 203, 240, 188, 238, 183, 190, 143, 203, 248, 184, 189, 206, 176, 143, 204,
-168, 143, 204, 170, 143, 204, 178, 143, 204, 182, 143, 204, 184, 143, 204, 189,
-143, 204, 192, 143, 204, 194, 143, 204, 199, 224, 247, 143, 204, 208, 143, 204,
-213, 224, 229, 143, 204, 226, 143, 204, 231, 143, 204, 234, 143, 204, 238, 143,
-204, 242, 143, 204, 245, 225, 166, 143, 204, 252, 143, 204, 254, 185, 249, 197,
-188, 225, 180, 197, 196, 196, 174, 225, 183, 143, 205, 180, 206, 177, 225, 191,
-143, 205, 187, 143, 205, 189, 143, 205, 196, 193, 193, 143, 205, 201, 225, 207,
-225, 215, 225, 214, 143, 205, 211, 225, 218, 143, 205, 216, 143, 205, 221, 143,
-205, 225, 225, 224, 143, 205, 231, 143, 205, 236, 143, 205, 242, 143, 205, 247,
-225, 240, 143, 206, 161, 143, 206, 167, 204, 254, 225, 245, 225, 252, 143, 206,
-179, 197, 208, 143, 206, 182, 187, 169, 226, 173, 143, 206, 193, 200, 233, 226,
-176, 226, 179, 143, 206, 205, 226, 181, 143, 206, 209, 226, 187, 196, 190, 189,
-226, 226, 190, 143, 206, 222, 143, 206, 228, 226, 197, 143, 206, 234, 143, 206,
-239, 143, 206, 243, 143, 206, 248, 143, 206, 253, 143, 207, 163, 143, 207, 168,
-226, 208, 226, 211, 143, 207, 176, 143, 207, 179, 143, 207, 182, 143, 207, 186,
-226, 218, 143, 207, 189, 143, 207, 192, 143, 207, 195, 182, 235, 192, 208, 186,
-189, 226, 230, 143, 207, 212, 181, 206, 203, 164, 185, 220, 143, 207, 225, 143,
-207, 228, 143, 207, 234, 200, 163, 226, 239, 226, 238, 200, 234, 143, 207, 244,
-202, 203, 143, 207, 252, 143, 208, 161, 226, 252, 200, 216, 227, 162, 143, 208,
-173, 176, 235, 143, 208, 185, 143, 208, 188, 143, 208, 190, 143, 208, 191, 143,
-208, 196, 143, 208, 200, 143, 208, 203, 143, 208, 207, 143, 208, 211, 227, 175,
-190, 205, 143, 208, 220, 143, 208, 223, 227, 180, 143, 208, 229, 143, 208, 235,
-143, 208, 238, 143, 208, 242, 143, 208, 244, 143, 208, 249, 143, 208, 252, 199,
-233, 190, 206, 176, 220, 143, 209, 172, 143, 209, 176, 143, 209, 178, 143, 209,
-181, 227, 202, 227, 203, 143, 209, 192, 178, 186, 143, 209, 198, 190, 247, 143,
-209, 206, 143, 209, 208, 143, 209, 211, 143, 209, 216, 143, 209, 219, 227, 221,
-143, 209, 223, 227, 227, 143, 209, 229, 227, 234, 227, 237, 143, 209, 234, 143,
-209, 239, 143, 209, 242, 181, 232, 143, 209, 244, 227, 250, 227, 252, 227, 247,
-143, 210, 163, 143, 210, 167, 195, 222, 228, 184, 228, 170, 228, 172, 143, 210,
-180, 143, 210, 182, 228, 176, 143, 210, 189, 143, 210, 191, 143, 210, 196, 200,
-207, 228, 189, 143, 210, 207, 198, 198, 143, 210, 212, 143, 210, 218, 143, 210,
-224, 228, 194, 143, 210, 231, 143, 210, 233, 143, 210, 237, 228, 213, 143, 210,
-244, 228, 216, 143, 210, 254, 143, 211, 164, 202, 198, 143, 211, 171, 143, 211,
-173, 206, 179, 143, 211, 176, 228, 234, 228, 236, 143, 211, 184, 143, 211, 187,
-228, 245, 228, 246, 143, 211, 199, 228, 250, 181, 234, 143, 211, 205, 143, 211,
-209, 229, 162, 143, 211, 215, 186, 217, 186, 176, 193, 200, 229, 174, 143, 211,
-230, 229, 179, 229, 177, 143, 211, 238, 143, 211, 243, 143, 211, 249, 143, 211,
-252, 229, 194, 188, 250, 143, 212, 166, 143, 212, 169, 143, 212, 174, 143, 212,
-177, 229, 206, 143, 212, 184, 143, 212, 187, 143, 212, 179, 229, 208, 143, 212,
-194, 229, 213, 203, 165, 229, 220, 143, 212, 206, 193, 161, 191, 165, 229, 229,
-229, 234, 143, 212, 221, 229, 239, 143, 212, 226, 143, 212, 229, 229, 251, 180,
-204, 143, 212, 240, 230, 163, 230, 169, 143, 212, 250, 143, 212, 254, 200, 237,
-230, 176, 230, 181, 143, 213, 171, 143, 213, 174, 143, 213, 178, 230, 192, 143,
-213, 183, 143, 213, 185, 143, 213, 187, 143, 213, 190, 143, 213, 194, 230, 203,
-185, 205, 143, 213, 203, 204, 215, 230, 212, 143, 213, 216, 204, 237, 143, 213,
-226, 230, 216, 192, 187, 143, 213, 228, 143, 213, 231, 191, 166, 143, 213, 234,
-207, 190, 190, 211, 184, 212, 143, 213, 241, 143, 213, 242, 176, 223, 143, 213,
-245, 143, 213, 250, 184, 213, 143, 213, 253, 182, 187, 187, 233, 143, 214, 170,
-143, 214, 175, 143, 214, 178, 196, 177, 143, 214, 183, 201, 229, 231, 181, 143,
-214, 193, 231, 171, 194, 220, 231, 174, 231, 178, 231, 177, 143, 214, 209, 231,
-187, 231, 190, 231, 193, 143, 214, 220, 143, 214, 224, 143, 214, 226, 143, 214,
-231, 143, 214, 236, 218, 170, 143, 214, 240, 143, 214, 244, 143, 214, 247, 143,
-214, 248, 231, 217, 143, 215, 161, 143, 215, 165, 143, 215, 167, 231, 226, 143,
-215, 171, 231, 232, 143, 215, 180, 143, 215, 184, 231, 236, 143, 215, 195, 203,
-167, 178, 234, 143, 215, 207, 143, 215, 209, 143, 215, 212, 143, 215, 216, 231,
-249, 231, 247, 183, 212, 232, 173, 143, 215, 233, 143, 215, 234, 195, 227, 232,
-166, 183, 213, 143, 215, 227, 143, 215, 253, 178, 174, 232, 174, 143, 216, 168,
-143, 216, 174, 143, 216, 176, 205, 233, 232, 207, 143, 216, 183, 143, 216, 187,
-186, 218, 143, 216, 191, 232, 203, 143, 216, 196, 143, 216, 198, 143, 216, 201,
-232, 206, 232, 212, 232, 226, 143, 216, 207, 143, 216, 212, 143, 216, 217, 198,
-161, 232, 211, 232, 216, 143, 216, 232, 190, 213, 143, 216, 236, 232, 231, 143,
-216, 240, 143, 216, 244, 143, 216, 247, 143, 216, 251, 143, 216, 254, 143, 217,
-162, 143, 217, 166, 143, 217, 171, 232, 209, 143, 217, 178, 177, 182, 143, 217,
-183, 143, 217, 188, 202, 195, 232, 254, 143, 217, 197, 143, 217, 201, 207, 207,
-233, 177, 143, 217, 216, 143, 217, 220, 177, 242, 143, 217, 228, 204, 244, 143,
-217, 232, 207, 206, 143, 217, 242, 233, 185, 143, 217, 247, 200, 205, 143, 217,
-252, 233, 193, 233, 190, 221, 177, 143, 218, 174, 205, 246, 143, 218, 178, 143,
-218, 183, 233, 200, 143, 218, 188, 143, 218, 193, 195, 238, 143, 218, 200, 143,
-218, 237, 233, 206, 143, 218, 210, 233, 219, 143, 218, 218, 143, 218, 222, 233,
-217, 233, 220, 233, 221, 233, 222, 194, 253, 203, 170, 233, 235, 195, 216, 143,
-218, 254, 143, 219, 162, 143, 219, 166, 143, 219, 172, 143, 219, 174, 233, 251,
-143, 219, 177, 233, 253, 233, 247, 234, 167, 143, 219, 192, 143, 219, 196, 234,
-165, 143, 219, 203, 205, 230, 234, 175, 143, 219, 214, 143, 219, 217, 143, 219,
-222, 143, 219, 226, 234, 187, 143, 219, 232, 143, 219, 237, 234, 192, 143, 219,
-248, 143, 219, 250, 234, 197, 143, 220, 164, 222, 167, 179, 185, 185, 213, 234,
-206, 234, 210, 182, 222, 194, 222, 194, 181, 143, 220, 190, 143, 220, 192, 184,
-211, 143, 220, 195, 143, 220, 197, 234, 227, 143, 220, 206, 234, 235, 234, 236,
-234, 233, 143, 220, 214, 179, 236, 143, 220, 222, 234, 243, 143, 220, 228, 143,
-220, 233, 234, 247, 143, 220, 240, 143, 220, 243, 235, 162, 143, 220, 250, 143,
-220, 254, 202, 164, 143, 221, 166, 179, 208, 143, 221, 173, 235, 178, 235, 180,
-179, 209, 235, 185, 191, 168, 143, 221, 189, 143, 221, 193, 143, 221, 197, 143,
-221, 199, 235, 194, 235, 196, 143, 221, 210, 191, 199, 143, 221, 217, 186, 190,
-235, 199, 143, 221, 229, 181, 205, 143, 221, 235, 235, 209, 143, 221, 243, 143,
-221, 248, 235, 216, 198, 201, 143, 222, 162, 235, 219, 180, 210, 207, 192, 235,
-227, 235, 221, 143, 222, 180, 143, 222, 183, 143, 222, 191, 235, 226, 143, 222,
-189, 235, 245, 235, 240, 235, 244, 143, 222, 201, 143, 222, 202, 201, 232, 183,
-217, 181, 196, 143, 222, 213, 218, 206, 143, 222, 221, 143, 222, 224, 195, 171,
-236, 175, 143, 222, 233, 236, 181, 190, 221, 208, 174, 143, 222, 250, 236, 186,
-203, 198, 236, 194, 185, 215, 192, 213, 236, 202, 178, 236, 194, 177, 143, 223,
-178, 199, 229, 188, 193, 143, 223, 187, 143, 223, 191, 143, 223, 194, 236, 219,
-192, 214, 143, 223, 201, 143, 223, 202, 177, 219, 143, 223, 209, 143, 223, 211,
-143, 223, 214, 143, 223, 218, 143, 223, 222, 143, 223, 227, 143, 223, 230, 236,
-240, 236, 238, 143, 223, 242, 236, 245, 236, 244, 143, 223, 250, 236, 247, 237,
-169, 236, 253, 143, 224, 171, 236, 254, 143, 224, 177, 143, 224, 181, 143, 224,
-184, 189, 179, 237, 175, 237, 179, 143, 224, 198, 237, 186, 191, 200, 143, 224,
-209, 143, 224, 212, 188, 214, 143, 224, 219, 198, 240, 237, 199, 143, 224, 225,
-143, 224, 230, 237, 210, 143, 224, 235, 143, 224, 239, 206, 216, 143, 224, 248,
-237, 217, 237, 219, 143, 225, 166, 143, 225, 170, 191, 201, 143, 225, 177, 237,
-231, 202, 213, 203, 248, 183, 222, 237, 233, 143, 225, 195, 143, 225, 197, 237,
-254, 143, 225, 203, 143, 225, 206, 237, 248, 194, 164, 143, 225, 212, 143, 225,
-216, 238, 167, 238, 166, 198, 187, 143, 225, 223, 143, 225, 226, 238, 175, 206,
-203, 237, 238, 205, 184, 143, 225, 241, 143, 225, 245, 238, 184, 143, 225, 251,
-143, 226, 163, 143, 226, 173, 143, 226, 169, 201, 244, 143, 226, 178, 143, 226,
-179, 143, 226, 185, 238, 192, 143, 226, 193, 143, 226, 199, 143, 226, 203, 143,
-226, 209, 143, 226, 212, 188, 242, 143, 226, 220, 189, 183, 185, 243, 143, 226,
-228, 238, 204, 143, 226, 237, 143, 226, 240, 238, 208, 238, 211, 143, 226, 254,
-238, 216, 143, 227, 164, 191, 203, 182, 252, 143, 227, 179, 143, 227, 182, 143,
-227, 187, 143, 227, 193, 143, 227, 198, 143, 227, 203, 143, 227, 207, 143, 227,
-213, 197, 180, 143, 227, 223, 143, 227, 226, 200, 173, 143, 227, 236, 143, 227,
-242, 189, 198, 143, 227, 251, 143, 227, 254, 143, 228, 164, 143, 228, 169, 238,
-248, 143, 228, 181, 143, 228, 188, 143, 228, 193, 143, 228, 200, 143, 228, 205,
-181, 248, 143, 228, 212, 143, 228, 214, 191, 238, 239, 162, 207, 163, 143, 228,
-230, 238, 253, 143, 228, 235, 143, 228, 241, 143, 228, 243, 239, 171, 143, 229,
-161, 143, 229, 167, 143, 229, 172, 143, 229, 176, 143, 229, 181, 143, 229, 183,
-143, 229, 188, 143, 229, 195, 239, 178, 182, 192, 143, 229, 207, 143, 229, 212,
-143, 229, 217, 143, 229, 222, 239, 197, 239, 195, 239, 196, 143, 229, 231, 143,
-229, 236, 143, 229, 238, 143, 229, 241, 239, 206, 239, 209, 239, 216, 196, 185,
-239, 217, 143, 230, 164, 239, 221, 239, 224, 143, 230, 173, 143, 230, 176, 239,
-234, 239, 235, 198, 174, 239, 243, 201, 236, 143, 230, 201, 143, 230, 203, 193,
-203, 239, 251, 143, 230, 214, 143, 230, 217, 240, 165, 198, 171, 143, 230, 224,
-231, 161, 240, 168, 143, 230, 233, 143, 230, 237, 143, 230, 240, 191, 253, 143,
-230, 242, 240, 186, 143, 230, 249, 143, 230, 250, 206, 237, 188, 251, 206, 238,
-240, 195, 143, 231, 167, 240, 199, 240, 201, 240, 205, 192, 196, 240, 208, 240,
-211, 240, 215, 143, 231, 191, 240, 217, 240, 223, 143, 231, 199, 240, 228, 202,
-220, 143, 231, 210, 240, 231, 143, 231, 223, 143, 231, 228, 143, 231, 235, 240,
-236, 143, 231, 240, 202, 199, 240, 243, 143, 231, 249, 143, 231, 252, 143, 232,
-161, 143, 232, 167, 143, 232, 170, 179, 220, 180, 234, 143, 232, 180, 143, 232,
-185, 201, 247, 143, 232, 190, 143, 232, 195, 143, 232, 199, 200, 244, 143, 232,
-202, 200, 211, 187, 244, 143, 232, 209, 143, 232, 211, 143, 232, 216, 143, 232,
-220, 143, 232, 223, 143, 232, 230, 241, 189, 241, 190, 143, 232, 242, 188, 243,
-241, 198, 143, 232, 251, 143, 233, 162, 194, 204, 195, 243, 143, 233, 170, 143,
-233, 173, 241, 209, 241, 211, 241, 215, 241, 214, 241, 217, 143, 233, 194, 143,
-233, 197, 241, 219, 143, 233, 204, 143, 233, 207, 241, 225, 241, 229, 241, 233,
-185, 252, 143, 233, 218, 241, 238, 143, 233, 228, 143, 233, 231, 143, 233, 236,
-143, 233, 240, 241, 249, 143, 233, 247, 143, 233, 254, 143, 234, 167, 242, 163,
-242, 166, 143, 234, 178, 143, 234, 182, 179, 161, 143, 234, 187, 143, 234, 189,
-143, 234, 194, 143, 234, 200, 143, 234, 205, 143, 234, 209, 143, 234, 215, 242,
-184, 143, 234, 223, 143, 234, 226, 143, 234, 230, 143, 234, 234, 242, 196, 143,
-234, 242, 194, 228, 143, 234, 247, 143, 234, 251, 143, 235, 161, 242, 218, 143,
-235, 168, 143, 235, 172, 143, 235, 177, 201, 201, 143, 235, 186, 143, 235, 188,
-143, 235, 194, 143, 235, 200, 143, 235, 205, 143, 235, 211, 242, 233, 196, 187,
-242, 236, 143, 235, 222, 178, 170, 143, 235, 225, 242, 245, 143, 235, 229, 143,
-235, 234, 242, 247, 243, 165, 177, 173, 143, 235, 248, 143, 235, 252, 143, 236,
-163, 143, 236, 167, 143, 236, 173, 143, 236, 175, 243, 170, 143, 236, 180, 143,
-236, 183, 143, 236, 186, 243, 186, 143, 236, 193, 143, 236, 198, 143, 236, 202,
-243, 191, 143, 236, 207, 143, 236, 210, 243, 193, 243, 195, 188, 175, 243, 200,
-243, 203, 206, 219, 243, 207, 143, 236, 238, 221, 224, 143, 236, 242, 185, 245,
-243, 217, 143, 236, 247, 143, 236, 252, 243, 228, 243, 231, 143, 237, 168, 143,
-237, 175, 143, 237, 178, 143, 237, 182, 201, 161, 143, 237, 194, 240, 237, 143,
-237, 202, 243, 245, 143, 237, 210, 143, 237, 214, 206, 182, 143, 237, 222, 143,
-237, 224, 161, 170, 161, 220, 163, 181, 161, 169, 163, 201, 163, 211, 161, 207,
-163, 231, 163, 241, 161, 208, 142, 165, 142, 175, 142, 185, 142, 195, 142, 205,
-142, 215, 161, 177
- });
-
- super.setUp();
+ @Override public void test_CodecDynamic() throws CharacterCodingException {
+ encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
+ decoder.onMalformedInput(CodingErrorAction.REPORT);
+ CharBuffer inputCB = CharBuffer.allocate(65536);
+ for (char codePoint = 0; codePoint <= 0xfffe; ++codePoint) {
+ if (encoder.canEncode(codePoint)) {
+ inputCB.put(codePoint);
+ }
}
-
- @Override
- public void test_CodecDynamic () throws CharacterCodingException {
- encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
- decoder.onMalformedInput(CodingErrorAction.REPORT);
- CharBuffer inputCB = CharBuffer.allocate(65536);
- for (int code = 32; code <= 65533; code ++) {
- if ((encoder.canEncode((char) code))
- && (code != 165) && (code != 8254)) {
- inputCB.put((char) code);
- }
- }
- inputCB.rewind();
- ByteBuffer intermediateBB = encoder.encode(inputCB);
- inputCB.rewind();
- intermediateBB.rewind();
- CharBuffer outputCB = decoder.decode(intermediateBB);
- outputCB.rewind();
- assertEqualCBs("decode(encode(A)) must be identical with A!",
- inputCB, outputCB);
- }
-
+ inputCB.rewind();
+ ByteBuffer intermediateBB = encoder.encode(inputCB);
+ inputCB.rewind();
+ intermediateBB.rewind();
+ CharBuffer outputCB = decoder.decode(intermediateBB);
+ outputCB.rewind();
+ assertEqualCBs("decode(encode(A)) must be identical with A!", inputCB, outputCB);
+ }
}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java
deleted file mode 100644
index 373c97f..0000000
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_EUC_JP_Android.java
+++ /dev/null
@@ -1,523 +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.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.CodingErrorAction;
-
-/** Note: ICU behaves differently from the RI */
-
-public class OldCharset_MultiByte_EUC_JP_Android extends OldCharset_AbstractTest {
-
- protected void setUp() throws Exception {
- charsetName = "EUC-JP";
-
- 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,
-161, 162, 163, 164, /*165,*/ 166, 167, 168, 169, 170, 172, 174, 175, 176, 177, 180,
-182, 184, 186, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
-204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220,
-221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
-237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252,
-253, 254, 255, 256, 266, 278, 288, 298, 308, 318, 328, 338, 348, 358, 368, 378,
-461, 471, 501, 711, 728, 900, 910, 920, 931, 941, 951, 961, 971, 1025, 1035, 1045,
-1055, 1065, 1075, 1085, 1095, 1105, 1115, 8208, 8220, 8230, 8240, 8251, 8451, 8470, 8482, 8592,
-8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472, 9484, 9495, 9507,
-9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298, 12308, 12353, 12363,
-12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493, 12503, 12513, 12523,
-12533, 19968, 19978, 19988, 19998, 20008, 20018, 20028, 20039, 20049, 20060, 20072, 20083, 20094, 20104, 20114,
-20124, 20134, 20144, 20154, 20164, 20174, 20184, 20194, 20205, 20215, 20225, 20235, 20245, 20270, 20280, 20290,
-20300, 20310, 20320, 20330, 20341, 20351, 20361, 20371, 20381, 20395, 20405, 20415, 20425, 20436, 20447, 20462,
-20472, 20484, 20494, 20504, 20514, 20524, 20534, 20544, 20554, 20565, 20575, 20586, 20596, 20608, 20618, 20628,
-20638, 20650, 20660, 20670, 20681, 20691, 20701, 20711, 20721, 20731, 20742, 20752, 20762, 20775, 20785, 20795,
-20805, 20815, 20826, 20836, 20846, 20856, 20866, 20876, 20886, 20896, 20906, 20916, 20926, 20936, 20946, 20956,
-20966, 20976, 20986, 20996, 21006, 21016, 21026, 21038, 21048, 21059, 21069, 21079, 21089, 21102, 21112, 21122,
-21132, 21142, 21152, 21162, 21172, 21182, 21192, 21202, 21212, 21222, 21232, 21242, 21253, 21263, 21273, 21283,
-21293, 21304, 21314, 21324, 21335, 21345, 21356, 21367, 21378, 21390, 21400, 21412, 21422, 21432, 21442, 21452,
-21462, 21472, 21482, 21493, 21505, 21515, 21530, 21542, 21553, 21563, 21574, 21585, 21598, 21608, 21619, 21629,
-21640, 21650, 21660, 21670, 21681, 21691, 21702, 21720, 21730, 21740, 21750, 21760, 21772, 21782, 21802, 21813,
-21824, 21834, 21846, 21856, 21883, 21894, 21905, 21916, 21927, 21938, 21951, 21961, 21971, 21982, 21993, 22006,
-22021, 22031, 22041, 22057, 22067, 22077, 22089, 22100, 22110, 22120, 22130, 22144, 22154, 22164, 22174, 22184,
-22195, 22206, 22216, 22227, 22237, 22247, 22257, 22269, 22279, 22289, 22299, 22309, 22319, 22331, 22341, 22351,
-22369, 22379, 22389, 22399, 22409, 22419, 22429, 22439, 22451, 22461, 22471, 22482, 22492, 22502, 22512, 22522,
-22532, 22549, 22559, 22570, 22580, 22591, 22601, 22612, 22622, 22632, 22642, 22652, 22663, 22675, 22685, 22696,
-22706, 22716, 22727, 22737, 22748, 22761, 22771, 22781, 22793, 22803, 22813, 22823, 22833, 22846, 22856, 22866,
-22877, 22887, 22898, 22908, 22922, 22933, 22943, 22956, 22967, 22977, 22987, 23001, 23011, 23022, 23035, 23049,
-23059, 23070, 23080, 23093, 23104, 23116, 23130, 23141, 23159, 23179, 23190, 23200, 23212, 23224, 23234, 23244,
-23254, 23264, 23274, 23285, 23296, 23307, 23318, 23329, 23340, 23350, 23360, 23371, 23381, 23391, 23401, 23411,
-23421, 23431, 23441, 23451, 23461, 23471, 23481, 23491, 23501, 23511, 23521, 23531, 23541, 23551, 23561, 23571,
-23582, 23592, 23602, 23612, 23622, 23632, 23642, 23652, 23662, 23673, 23687, 23697, 23709, 23720, 23730, 23740,
-23751, 23762, 23773, 23784, 23794, 23805, 23815, 23825, 23835, 23846, 23857, 23869, 23880, 23890, 23900, 23913,
-23923, 23934, 23944, 23954, 23965, 23975, 23986, 23996, 24007, 24018, 24029, 24039, 24049, 24059, 24070, 24081,
-24091, 24101, 24111, 24125, 24135, 24145, 24155, 24168, 24178, 24188, 24199, 24213, 24224, 24234, 24245, 24255,
-24265, 24275, 24285, 24296, 24307, 24318, 24328, 24339, 24349, 24359, 24369, 24379, 24389, 24400, 24411, 24422,
-24432, 24442, 24452, 24463, 24473, 24484, 24494, 24504, 24515, 24525, 24535, 24545, 24555, 24565, 24575, 24586,
-24596, 24607, 24617, 24627, 24640, 24650, 24660, 24671, 24681, 24693, 24703, 24713, 24723, 24733, 24743, 24753,
-24763, 24773, 24783, 24793, 24803, 24816, 24826, 24838, 24848, 24858, 24871, 24881, 24892, 24902, 24915, 24925,
-24935, 24945, 24955, 24967, 24977, 24988, 24999, 25010, 25020, 25030, 25040, 25052, 25062, 25074, 25084, 25095,
-25105, 25115, 25126, 25136, 25147, 25158, 25168, 25178, 25188, 25198, 25209, 25219, 25229, 25239, 25254, 25265,
-25275, 25285, 25295, 25305, 25322, 25332, 25342, 25352, 25363, 25375, 25385, 25397, 25407, 25417, 25427, 25445,
-25457, 25467, 25479, 25490, 25502, 25512, 25522, 25533, 25544, 25554, 25564, 25577, 25587, 25606, 25616, 25628,
-25638, 25648, 25658, 25675, 25688, 25699, 25709, 25720, 25731, 25743, 25753, 25763, 25773, 25785, 25796, 25806,
-25816, 25826, 25836, 25846, 25856, 25866, 25876, 25886, 25897, 25908, 25918, 25928, 25938, 25949, 25959, 25970,
-25981, 25991, 26001, 26011, 26021, 26031, 26041, 26051, 26062, 26072, 26082, 26092, 26105, 26115, 26125, 26140,
-26150, 26160, 26172, 26182, 26193, 26203, 26214, 26224, 26234, 26244, 26254, 26264, 26274, 26285, 26296, 26306,
-26316, 26326, 26336, 26347, 26357, 26367, 26377, 26387, 26397, 26407, 26417, 26429, 26439, 26449, 26460, 26470,
-26480, 26491, 26501, 26511, 26521, 26534, 26544, 26555, 26565, 26575, 26585, 26596, 26606, 26617, 26627, 26643,
-26653, 26663, 26673, 26683, 26693, 26704, 26715, 26727, 26737, 26747, 26757, 26767, 26778, 26789, 26799, 26809,
-26820, 26831, 26841, 26851, 26861, 26873, 26884, 26894, 26905, 26915, 26928, 26939, 26949, 26963, 26973, 26984,
-26994, 27004, 27018, 27028, 27040, 27051, 27063, 27073, 27083, 27094, 27106, 27117, 27129, 27139, 27151, 27161,
-27171, 27182, 27192, 27204, 27214, 27224, 27234, 27249, 27262, 27273, 27287, 27298, 27308, 27320, 27330, 27340,
-27350, 27364, 27376, 27386, 27396, 27407, 27419, 27431, 27442, 27453, 27463, 27474, 27485, 27495, 27507, 27517,
-27529, 27541, 27551, 27561, 27571, 27581, 27593, 27603, 27615, 27627, 27639, 27650, 27661, 27671, 27683, 27694,
-27704, 27714, 27725, 27735, 27746, 27757, 27768, 27778, 27788, 27798, 27809, 27819, 27832, 27842, 27852, 27862,
-27872, 27882, 27892, 27908, 27918, 27929, 27941, 27951, 27961, 27972, 27991, 28001, 28012, 28023, 28034, 28044,
-28054, 28074, 28084, 28095, 28106, 28117, 28127, 28137, 28147, 28160, 28170, 28181, 28191, 28201, 28214, 28227,
-28237, 28247, 28258, 28270, 28283, 28300, 28310, 28320, 28330, 28342, 28352, 28362, 28372, 28382, 28395, 28407,
-28417, 28428, 28438, 28448, 28458, 28470, 28481, 28495, 28505, 28516, 28526, 28536, 28546, 28556, 28566, 28576,
-28586, 28597, 28608, 28618, 28628, 28638, 28648, 28659, 28669, 28679, 28689, 28699, 28710, 28720, 28732, 28744,
-28756, 28766, 28779, 28789, 28801, 28814, 28824, 28836, 28846, 28856, 28872, 28883, 28893, 28913, 28925, 28935,
-28948, 28958, 28971, 28982, 28993, 29003, 29013, 29024, 29036, 29049, 29060, 29071, 29081, 29096, 29106, 29118,
-29128, 29138, 29148, 29158, 29173, 29183, 29193, 29203, 29213, 29224, 29234, 29244, 29254, 29264, 29274, 29287,
-29297, 29307, 29319, 29330, 29344, 29356, 29366, 29377, 29388, 29398, 29408, 29420, 29431, 29442, 29453, 29463,
-29474, 29484, 29494, 29507, 29517, 29527, 29539, 29550, 29560, 29571, 29582, 29592, 29602, 29613, 29623, 29634,
-29644, 29654, 29664, 29674, 29684, 29694, 29705, 29722, 29732, 29742, 29753, 29763, 29773, 29783, 29794, 29805,
-29822, 29833, 29848, 29858, 29870, 29881, 29896, 29907, 29918, 29928, 29938, 29948, 29958, 29969, 29980, 29990,
-30000, 30010, 30020, 30030, 30041, 30052, 30063, 30073, 30085, 30095, 30105, 30115, 30129, 30140, 30150, 30162,
-30172, 30183, 30193, 30204, 30215, 30226, 30236, 30246, 30256, 30266, 30276, 30290, 30300, 30311, 30321, 30331,
-30341, 30352, 30362, 30372, 30382, 30392, 30402, 30412, 30422, 30432, 30442, 30452, 30462, 30472, 30482, 30492,
-30502, 30516, 30526, 30538, 30550, 30560, 30570, 30580, 30590, 30603, 30613, 30623, 30634, 30645, 30655, 30665,
-30677, 30687, 30697, 30707, 30722, 30732, 30749, 30759, 30770, 30783, 30796, 30812, 30824, 30834, 30844, 30854,
-30865, 30877, 30887, 30897, 30907, 30917, 30928, 30938, 30948, 30959, 30970, 30982, 30992, 31002, 31013, 31025,
-31035, 31045, 31055, 31066, 31077, 31090, 31100, 31114, 31124, 31137, 31147, 31160, 31170, 31183, 31194, 31204,
-31216, 31227, 31239, 31249, 31259, 31271, 31281, 31291, 31301, 31311, 31321, 31331, 31341, 31352, 31362, 31376,
-31390, 31401, 31411, 31423, 31433, 31443, 31453, 31464, 31476, 31486, 31496, 31508, 31518, 31528, 31539, 31549,
-31559, 31569, 31581, 31591, 31601, 31620, 31630, 31640, 31653, 31663, 31674, 31684, 31695, 31705, 31716, 31730,
-31740, 31750, 31761, 31771, 31781, 31793, 31805, 31818, 31828, 31838, 31849, 31859, 31869, 31879, 31890, 31902,
-31912, 31922, 31932, 31943, 31954, 31964, 31974, 31986, 31998, 32008, 32018, 32028, 32038, 32048, 32058, 32068,
-32078, 32089, 32099, 32110, 32120, 32130, 32140, 32150, 32162, 32172, 32182, 32194, 32204, 32215, 32225, 32235,
-32245, 32256, 32266, 32277, 32287, 32299, 32309, 32319, 32330, 32340, 32350, 32361, 32371, 32381, 32391, 32401,
-32411, 32566, 32579, 32589, 32600, 32611, 32621, 32631, 32642, 32652, 32662, 32673, 32685, 32696, 32707, 32718,
-32731, 32741, 32751, 32761, 32771, 32781, 32791, 32801, 32812, 32822, 32832, 32842, 32854, 32864, 32877, 32887,
-32897, 32907, 32918, 32929, 32939, 32952, 32963, 32973, 32983, 32993, 33005, 33016, 33026, 33046, 33056, 33068,
-33081, 33093, 33104, 33119, 33129, 33140, 33151, 33162, 33173, 33184, 33198, 33208, 33218, 33229, 33239, 33249,
-33259, 33269, 33279, 33289, 33299, 33309, 33320, 33330, 33344, 33355, 33366, 33376, 33386, 33396, 33406, 33417,
-33428, 33439, 33449, 33459, 33469, 33488, 33498, 33508, 33519, 33529, 33539, 33550, 33560, 33570, 33580, 33590,
-33600, 33610, 33620, 33648, 33659, 33669, 33682, 33692, 33702, 33713, 33725, 33735, 33745, 33756, 33768, 33778,
-33788, 33798, 33809, 33824, 33834, 33845, 33861, 33871, 33881, 33891, 33901, 33911, 33921, 33931, 33941, 33951,
-33961, 33972, 33982, 33992, 34003, 34023, 34033, 34043, 34054, 34064, 34074, 34084, 34095, 34109, 34120, 34130,
-34140, 34152, 34167, 34177, 34187, 34199, 34210, 34220, 34230, 34241, 34251, 34261, 34271, 34281, 34291, 34302,
-34314, 34326, 34337, 34349, 34360, 34370, 34381, 34391, 34401, 34411, 34421, 34440, 34451, 34465, 34475, 34485,
-34495, 34505, 34516, 34526, 34537, 34552, 34562, 34573, 34584, 34595, 34606, 34617, 34627, 34637, 34647, 34657,
-34670, 34680, 34690, 34700, 34711, 34722, 34732, 34746, 34756, 34766, 34777, 34787, 34797, 34807, 34817, 34827,
-34837, 34847, 34861, 34873, 34883, 34893, 34903, 34913, 34923, 34933, 34943, 34955, 34966, 34976, 34986, 34996,
-35006, 35018, 35028, 35038, 35048, 35058, 35068, 35078, 35088, 35098, 35109, 35120, 35130, 35140, 35151, 35162,
-35172, 35182, 35194, 35206, 35216, 35226, 35237, 35247, 35258, 35282, 35292, 35302, 35313, 35325, 35335, 35345,
-35355, 35365, 35375, 35386, 35397, 35408, 35419, 35429, 35440, 35450, 35460, 35471, 35481, 35491, 35501, 35511,
-35522, 35532, 35542, 35552, 35563, 35573, 35583, 35594, 35604, 35614, 35624, 35635, 35646, 35656, 35666, 35676,
-35686, 35696, 35708, 35722, 35732, 35742, 35895, 35905, 35915, 35925, 35937, 35947, 35957, 35970, 35980, 35992,
-36002, 36012, 36022, 36032, 36042, 36053, 36064, 36074, 36085, 36095, 36105, 36115, 36196, 36206, 36223, 36234,
-36245, 36255, 36267, 36277, 36288, 36298, 36308, 36319, 36330, 36340, 36351, 36361, 36372, 36382, 36394, 36404,
-36416, 36426, 36436, 36446, 36457, 36468, 36481, 36491, 36501, 36513, 36523, 36533, 36544, 36554, 36564, 36575,
-36587, 36599, 36610, 36620, 36630, 36640, 36650, 36660, 36670, 36681, 36691, 36701, 36763, 36773, 36783, 36794,
-36804, 36814, 36826, 36836, 36846, 36856, 36866, 36876, 36886, 36896, 36906, 36916, 36926, 36937, 36947, 36957,
-36967, 36978, 36988, 36999, 37009, 37019, 37029, 37039, 37053, 37063, 37074, 37084, 37096, 37108, 37118, 37128,
-37138, 37148, 37159, 37169, 37180, 37191, 37202, 37217, 37228, 37239, 37249, 37259, 37269, 37281, 37291, 37301,
-37311, 37321, 37331, 37341, 37351, 37361, 37371, 37381, 37392, 37404, 37414, 37424, 37434, 37444, 37454, 37464,
-37474, 37486, 37496, 37507, 37517, 37527, 37540, 37551, 37561, 37571, 37581, 37591, 37601, 37612, 37624, 37634,
-37645, 37656, 37666, 37676, 37686, 37700, 37712, 37722, 37732, 37742, 37754, 37768, 37778, 37790, 37800, 37812,
-37825, 37835, 37846, 37857, 37879, 37889, 37901, 37911, 37921, 37931, 37941, 37951, 37962, 37973, 37983, 37994,
-38005, 38015, 38263, 38274, 38284, 38294, 38304, 38315, 38326, 38339, 38349, 38360, 38370, 38428, 38438, 38449,
-38459, 38475, 38486, 38497, 38508, 38518, 38529, 38539, 38549, 38559, 38569, 38579, 38592, 38602, 38613, 38623,
-38633, 38646, 38656, 38666, 38678, 38689, 38704, 38717, 38728, 38738, 38748, 38758, 38769, 38779, 38789, 38799,
-38809, 38819, 38829, 38840, 38851, 38861, 38871, 38881, 38893, 38903, 38913, 38924, 38934, 38944, 38955, 38965,
-38980, 38990, 39000, 39010, 39020, 39080, 39092, 39103, 39116, 39131, 39141, 39151, 39164, 39175, 39185, 39195,
-39206, 39217, 39227, 39237, 39248, 39259, 39318, 39333, 39344, 39354, 39364, 39376, 39386, 39399, 39409, 39419,
-39429, 39439, 39449, 39459, 39469, 39479, 39489, 39499, 39509, 39519, 39529, 39592, 39602, 39612, 39622, 39632,
-39643, 39653, 39663, 39673, 39683, 39693, 39704, 39714, 39725, 39735, 39745, 39755, 39765, 39777, 39787, 39797,
-39807, 39817, 39827, 39837, 39847, 39857, 39867, 39878, 39888, 39899, 39909, 39919, 39929, 39940, 39951, 39961,
-39971, 39981, 39991, 40001, 40014, 40024, 40035, 40046, 40056, 40165, 40176, 40194, 40206, 40216, 40227, 40239,
-40250, 40260, 40272, 40284, 40297, 40310, 40323, 40333, 40343, 40353, 40363, 40373, 40383, 40393, 40403, 40414,
-40425, 40435, 40445, 40455, 40465, 40475, 40565, 40575, 40587, 40597, 40607, 40617, 40627, 40638, 40648, 40658,
-40668, 40679, 40689, 40699, 40711, 40721, 40731, 40742, 40753, 40763, 40773, 40783, 40794, 40806, 40816, 40826,
-40845, 40855, 40865, 65281, 65291, 65301, 65311, 65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401,
-65411, 65421, 65431, 65507
- });
-
- 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,
-143, 162, 194, 142, 224, 142, 225, 143, 162, 240, 143, 162, 195, 161, 248, 161,
-175, 143, 162, 237, 143, 162, 236, 142, 226, 143, 162, 238, 143, 162, 180, 161,
-235, 161, 222, 161, 173, 162, 249, 143, 162, 177, 143, 162, 235, 143, 162, 196,
-143, 170, 162, 143, 170, 161, 143, 170, 164, 143, 170, 170, 143, 170, 163, 143,
-170, 169, 143, 169, 161, 143, 170, 174, 143, 170, 178, 143, 170, 177, 143, 170,
-180, 143, 170, 179, 143, 170, 192, 143, 170, 191, 143, 170, 194, 143, 170, 193,
-143, 170, 208, 143, 170, 210, 143, 170, 209, 143, 170, 212, 143, 170, 216, 143,
-170, 211, 161, 223, 143, 169, 172, 143, 170, 227, 143, 170, 226, 143, 170, 229,
-143, 170, 228, 143, 170, 242, 143, 169, 176, 143, 169, 206, 143, 171, 162, 143,
-171, 161, 143, 171, 164, 143, 171, 170, 143, 171, 163, 143, 171, 169, 143, 169,
-193, 143, 171, 174, 143, 171, 178, 143, 171, 177, 143, 171, 180, 143, 171, 179,
-143, 171, 192, 143, 171, 191, 143, 171, 194, 143, 171, 193, 143, 169, 195, 143,
-171, 208, 143, 171, 210, 143, 171, 209, 143, 171, 212, 143, 171, 216, 143, 171,
-211, 161, 224, 143, 169, 204, 143, 171, 227, 143, 171, 226, 143, 171, 229, 143,
-171, 228, 143, 171, 242, 143, 169, 208, 143, 171, 243, 143, 170, 167, 143, 170,
-175, 143, 170, 182, 143, 170, 189, 143, 170, 197, 143, 170, 200, 143, 171, 203,
-143, 171, 206, 143, 169, 173, 143, 170, 221, 143, 169, 175, 143, 170, 232, 143,
-171, 245, 143, 170, 166, 143, 170, 237, 143, 171, 185, 143, 162, 176, 143, 162,
-175, 143, 162, 184, 143, 166, 233, 166, 168, 166, 178, 143, 166, 242, 166, 199,
-166, 209, 143, 166, 250, 167, 167, 143, 167, 203, 167, 166, 167, 177, 167, 187,
-167, 212, 167, 223, 167, 233, 167, 215, 143, 167, 251, 161, 190, 161, 200, 161,
-196, 162, 243, 162, 168, 161, 238, 143, 162, 241, 143, 162, 239, 162, 171, 162,
-205, 162, 207, 162, 187, 162, 229, 162, 202, 161, 232, 162, 226, 161, 226, 162,
-227, 162, 190, 162, 221, 162, 222, 168, 161, 168, 163, 168, 177, 168, 178, 168,
-184, 168, 181, 168, 182, 162, 163, 162, 165, 162, 167, 162, 161, 162, 254, 161,
-250, 161, 234, 162, 246, 161, 161, 161, 212, 161, 204, 164, 161, 164, 171, 164,
-181, 164, 191, 164, 201, 164, 211, 164, 221, 164, 231, 164, 241, 161, 171, 165,
-165, 165, 175, 165, 185, 165, 195, 165, 205, 165, 215, 165, 225, 165, 235, 165,
-245, 176, 236, 190, 229, 179, 238, 190, 231, 143, 176, 169, 182, 250, 208, 167,
-143, 176, 178, 143, 176, 179, 143, 176, 181, 143, 176, 183, 198, 253, 180, 165,
-205, 189, 184, 223, 176, 161, 203, 242, 208, 183, 191, 205, 208, 188, 208, 186,
-201, 213, 143, 176, 201, 208, 193, 208, 195, 180, 235, 143, 176, 214, 143, 176,
-217, 143, 176, 221, 191, 173, 143, 176, 231, 143, 176, 235, 143, 176, 238, 143,
-176, 223, 143, 176, 242, 202, 187, 187, 200, 143, 177, 162, 143, 177, 168, 176,
-205, 213, 165, 191, 175, 202, 216, 143, 177, 187, 208, 215, 208, 216, 189, 164,
-202, 240, 143, 177, 203, 143, 177, 207, 143, 177, 211, 143, 177, 216, 208, 235,
-182, 230, 143, 177, 223, 143, 177, 228, 208, 243, 143, 177, 236, 143, 177, 242,
-194, 166, 208, 250, 143, 177, 251, 143, 178, 163, 143, 178, 167, 143, 178, 172,
-208, 253, 183, 185, 209, 161, 143, 178, 185, 143, 178, 189, 193, 206, 143, 178,
-197, 202, 200, 143, 178, 202, 143, 178, 210, 209, 179, 143, 178, 218, 143, 178,
-223, 209, 184, 189, 188, 143, 178, 231, 197, 222, 143, 178, 237, 209, 194, 197,
-181, 209, 196, 209, 198, 209, 204, 180, 167, 209, 209, 186, 227, 143, 178, 252,
-143, 179, 161, 143, 179, 164, 244, 165, 189, 232, 209, 224, 189, 208, 209, 227,
-209, 230, 143, 179, 183, 143, 179, 184, 209, 233, 183, 244, 196, 230, 193, 176,
-143, 179, 193, 143, 179, 199, 143, 179, 201, 143, 179, 203, 143, 179, 206, 143,
-179, 209, 143, 179, 212, 178, 195, 197, 216, 207, 171, 179, 175, 143, 179, 232,
-240, 213, 143, 179, 239, 210, 171, 143, 179, 246, 188, 219, 202, 241, 210, 183,
-186, 252, 210, 186, 143, 180, 175, 210, 190, 143, 180, 182, 143, 180, 183, 198,
-238, 143, 180, 187, 143, 180, 190, 210, 203, 210, 204, 143, 180, 198, 206, 210,
-143, 180, 204, 210, 209, 143, 180, 212, 187, 178, 193, 208, 188, 232, 143, 180,
-224, 194, 254, 143, 180, 227, 210, 222, 177, 165, 143, 180, 230, 200, 221, 143,
-180, 236, 202, 173, 202, 242, 198, 221, 143, 180, 244, 188, 254, 204, 163, 204,
-191, 143, 181, 164, 210, 240, 143, 181, 170, 143, 181, 173, 143, 181, 179, 143,
-181, 183, 143, 181, 185, 211, 166, 211, 175, 143, 181, 191, 143, 181, 193, 143,
-181, 197, 143, 181, 202, 176, 162, 143, 181, 206, 143, 181, 209, 211, 177, 143,
-181, 217, 211, 183, 143, 181, 225, 211, 193, 143, 181, 232, 143, 181, 236, 180,
-238, 183, 246, 143, 181, 244, 143, 181, 245, 143, 181, 249, 143, 182, 161, 143,
-182, 165, 143, 182, 167, 143, 182, 168, 143, 182, 170, 143, 182, 175, 143, 182,
-179, 178, 222, 143, 182, 182, 143, 182, 188, 143, 182, 195, 143, 182, 199, 143,
-182, 200, 180, 239, 143, 182, 210, 211, 230, 211, 231, 211, 233, 143, 182, 221,
-143, 182, 225, 143, 182, 231, 143, 182, 233, 211, 244, 211, 247, 143, 182, 244,
-143, 182, 250, 143, 182, 252, 185, 241, 143, 183, 165, 143, 183, 168, 143, 183,
-171, 143, 183, 177, 143, 183, 182, 212, 173, 143, 183, 188, 212, 175, 212, 179,
-143, 183, 197, 143, 183, 205, 212, 180, 212, 181, 212, 182, 143, 183, 220, 143,
-183, 225, 212, 184, 143, 183, 230, 143, 183, 231, 212, 191, 199, 184, 143, 183,
-239, 143, 183, 243, 180, 240, 143, 183, 251, 194, 196, 143, 184, 165, 180, 174,
-190, 236, 143, 184, 172, 143, 184, 173, 197, 227, 186, 201, 143, 184, 183, 212,
-199, 143, 184, 185, 143, 184, 189, 202, 232, 143, 184, 199, 203, 207, 143, 184,
-206, 143, 184, 208, 195, 197, 212, 219, 212, 224, 143, 184, 221, 143, 184, 222,
-212, 232, 202, 209, 143, 184, 228, 143, 184, 231, 194, 231, 188, 186, 212, 243,
-198, 224, 143, 184, 244, 143, 184, 248, 212, 252, 143, 185, 162, 143, 185, 167,
-199, 165, 143, 185, 172, 143, 185, 174, 197, 202, 143, 185, 182, 143, 185, 185,
-187, 207, 213, 172, 143, 185, 195, 143, 185, 198, 176, 249, 213, 178, 143, 185,
-210, 143, 185, 211, 143, 185, 215, 213, 183, 213, 180, 143, 185, 223, 186, 167,
-143, 185, 228, 143, 185, 231, 143, 185, 235, 143, 185, 238, 143, 185, 243, 143,
-185, 246, 143, 185, 251, 213, 191, 183, 249, 213, 197, 143, 186, 167, 143, 186,
-169, 143, 186, 171, 143, 186, 174, 213, 201, 213, 202, 143, 186, 182, 196, 220,
-213, 206, 213, 210, 143, 186, 187, 213, 212, 204, 210, 213, 216, 213, 218, 143,
-186, 196, 177, 167, 143, 186, 205, 176, 184, 205, 168, 143, 186, 213, 205, 198,
-213, 227, 143, 186, 221, 143, 186, 224, 178, 201, 213, 237, 195, 254, 188, 247,
-176, 211, 213, 245, 143, 186, 235, 213, 248, 143, 186, 244, 198, 244, 213, 252,
-214, 161, 143, 186, 248, 193, 216, 214, 165, 214, 168, 143, 187, 169, 214, 170,
-143, 187, 174, 193, 187, 143, 187, 181, 214, 176, 214, 180, 143, 187, 187, 143,
-187, 188, 178, 229, 143, 187, 192, 214, 183, 191, 242, 214, 194, 214, 193, 143,
-187, 201, 143, 187, 203, 143, 187, 206, 143, 187, 211, 214, 201, 214, 191, 191,
-243, 214, 205, 143, 187, 226, 143, 187, 230, 143, 187, 232, 214, 211, 143, 187,
-240, 143, 230, 244, 214, 217, 143, 187, 247, 214, 221, 192, 238, 185, 170, 184,
-202, 180, 172, 200, 193, 214, 230, 214, 231, 191, 227, 194, 211, 203, 185, 214,
-243, 143, 188, 181, 143, 188, 184, 143, 188, 187, 180, 179, 205, 196, 200, 223,
-196, 236, 214, 249, 143, 188, 201, 176, 195, 143, 188, 207, 206, 247, 179, 199,
-215, 163, 215, 168, 215, 172, 215, 176, 143, 188, 223, 181, 221, 143, 188, 227,
-184, 204, 188, 229, 143, 188, 239, 143, 188, 244, 143, 188, 247, 143, 188, 250,
-201, 167, 190, 180, 143, 189, 166, 183, 194, 143, 189, 171, 215, 208, 143, 189,
-178, 200, 249, 143, 189, 183, 191, 180, 199, 166, 187, 214, 143, 189, 195, 178,
-247, 199, 176, 215, 221, 143, 189, 210, 143, 189, 213, 143, 189, 217, 215, 226,
-143, 189, 220, 143, 189, 222, 215, 240, 143, 189, 228, 215, 239, 178, 184, 183,
-195, 143, 189, 236, 188, 189, 143, 189, 243, 143, 189, 246, 216, 166, 143, 189,
-253, 143, 190, 161, 190, 240, 143, 190, 170, 143, 190, 173, 193, 218, 194, 198,
-216, 185, 216, 180, 143, 190, 188, 182, 242, 216, 195, 143, 190, 202, 216, 198,
-143, 190, 209, 216, 216, 216, 215, 183, 197, 216, 213, 143, 190, 216, 216, 220,
-216, 225, 143, 190, 229, 198, 180, 183, 251, 143, 190, 239, 216, 234, 178, 251,
-143, 190, 246, 216, 239, 196, 168, 216, 246, 143, 191, 167, 178, 230, 216, 254,
-192, 239, 217, 165, 204, 225, 143, 191, 182, 143, 191, 184, 143, 191, 189, 143,
-191, 191, 202, 177, 200, 227, 217, 183, 143, 191, 197, 185, 179, 143, 191, 201,
-202, 250, 217, 187, 195, 180, 217, 188, 192, 219, 143, 191, 214, 143, 191, 216,
-189, 166, 217, 205, 143, 191, 225, 182, 180, 143, 191, 228, 143, 191, 231, 193,
-222, 194, 170, 143, 191, 244, 143, 191, 248, 143, 191, 252, 199, 177, 143, 192,
-167, 199, 211, 143, 192, 174, 191, 228, 183, 199, 143, 192, 180, 143, 192, 183,
-217, 231, 143, 192, 189, 217, 226, 143, 192, 195, 217, 236, 143, 192, 201, 217,
-211, 217, 238, 143, 192, 213, 183, 200, 143, 192, 217, 197, 166, 143, 192, 230,
-143, 192, 231, 204, 206, 183, 226, 143, 192, 238, 143, 192, 242, 143, 192, 247,
-199, 197, 179, 201, 143, 193, 161, 143, 193, 166, 218, 166, 197, 167, 181, 188,
-218, 177, 218, 181, 143, 193, 185, 143, 193, 188, 143, 193, 192, 143, 193, 196,
-218, 189, 202, 252, 218, 195, 143, 193, 206, 218, 201, 143, 193, 210, 218, 202,
-143, 193, 213, 202, 184, 200, 195, 218, 207, 192, 205, 187, 219, 202, 253, 218,
-211, 143, 193, 232, 143, 193, 236, 180, 251, 189, 220, 143, 193, 242, 218, 224,
-143, 193, 249, 218, 230, 143, 194, 166, 143, 194, 172, 195, 235, 143, 194, 179,
-143, 194, 182, 143, 194, 187, 179, 162, 218, 242, 195, 210, 218, 247, 218, 245,
-218, 248, 196, 170, 143, 194, 217, 219, 162, 143, 194, 224, 143, 194, 227, 219,
-163, 219, 165, 143, 194, 234, 219, 170, 194, 216, 205, 173, 143, 194, 241, 196,
-171, 219, 176, 188, 235, 181, 224, 143, 194, 249, 194, 188, 197, 206, 143, 195,
-161, 219, 191, 143, 195, 166, 219, 199, 143, 195, 170, 143, 195, 175, 219, 197,
-143, 195, 177, 143, 195, 181, 143, 195, 188, 199, 240, 143, 195, 193, 219, 207,
-219, 211, 143, 195, 184, 198, 202, 192, 242, 143, 195, 204, 143, 195, 207, 143,
-195, 212, 143, 195, 214, 143, 195, 217, 182, 205, 143, 195, 223, 201, 176, 143,
-195, 228, 143, 195, 233, 199, 223, 219, 231, 143, 195, 241, 143, 195, 245, 196,
-244, 219, 238, 180, 254, 143, 195, 254, 143, 196, 165, 220, 168, 143, 196, 173,
-220, 170, 220, 166, 196, 199, 191, 250, 220, 176, 220, 191, 143, 196, 193, 143,
-196, 195, 201, 246, 220, 194, 143, 196, 204, 143, 196, 209, 207, 176, 186, 231,
-207, 177, 220, 213, 143, 196, 222, 143, 196, 225, 220, 201, 185, 189, 143, 196,
-232, 143, 196, 234, 220, 229, 220, 223, 143, 196, 244, 143, 196, 245, 201, 184,
-220, 235, 220, 211, 220, 247, 220, 237, 143, 197, 170, 181, 204, 220, 243, 143,
-197, 180, 143, 197, 182, 143, 197, 187, 221, 161, 220, 253, 221, 168, 221, 166,
-221, 165, 143, 197, 206, 143, 197, 210, 143, 197, 213, 143, 197, 216, 221, 178,
-205, 243, 143, 197, 226, 143, 197, 230, 178, 164, 205, 223, 182, 214, 221, 188,
-143, 197, 244, 143, 197, 247, 143, 197, 249, 186, 208, 143, 197, 254, 189, 222,
-221, 205, 143, 198, 166, 143, 198, 171, 221, 213, 143, 198, 178, 143, 198, 182,
-221, 218, 221, 219, 221, 221, 143, 198, 192, 143, 198, 195, 143, 198, 199, 181,
-164, 221, 230, 143, 198, 209, 177, 202, 181, 225, 143, 198, 218, 180, 192, 221,
-233, 143, 198, 226, 143, 198, 230, 221, 235, 198, 217, 178, 173, 203, 215, 203,
-247, 202, 168, 143, 198, 246, 200, 231, 143, 198, 254, 143, 199, 163, 222, 165,
-143, 199, 170, 143, 199, 171, 143, 199, 174, 222, 172, 196, 197, 143, 199, 184,
-143, 199, 186, 190, 244, 143, 199, 189, 143, 199, 192, 179, 189, 179, 164, 143,
-199, 198, 205, 176, 143, 199, 203, 143, 199, 206, 143, 199, 208, 143, 199, 212,
-143, 199, 215, 222, 204, 143, 199, 221, 143, 199, 225, 189, 223, 143, 199, 231,
-222, 189, 222, 188, 222, 219, 178, 185, 143, 199, 237, 222, 220, 222, 218, 143,
-199, 251, 143, 200, 161, 222, 208, 143, 200, 165, 200, 174, 189, 224, 143, 200,
-170, 222, 228, 205, 207, 143, 200, 178, 143, 200, 183, 222, 237, 194, 218, 143,
-200, 187, 223, 163, 181, 249, 143, 200, 196, 143, 200, 198, 199, 249, 143, 200,
-204, 143, 200, 208, 222, 243, 143, 200, 212, 143, 200, 217, 189, 225, 196, 172,
-223, 166, 223, 173, 143, 200, 231, 143, 200, 237, 143, 200, 240, 223, 186, 143,
-200, 248, 183, 227, 143, 200, 254, 223, 190, 143, 201, 162, 143, 201, 163, 223,
-171, 143, 201, 169, 143, 201, 173, 223, 198, 223, 202, 195, 245, 223, 208, 143,
-201, 182, 143, 201, 185, 143, 201, 189, 143, 201, 192, 178, 208, 143, 201, 198,
-143, 201, 201, 177, 234, 143, 201, 208, 143, 201, 210, 223, 220, 223, 218, 206,
-245, 143, 201, 218, 223, 223, 223, 216, 223, 226, 143, 201, 230, 177, 235, 143,
-201, 234, 143, 201, 236, 193, 179, 143, 201, 242, 143, 201, 247, 223, 230, 143,
-201, 254, 223, 236, 143, 202, 162, 223, 239, 223, 237, 244, 166, 223, 241, 143,
-202, 174, 223, 245, 197, 245, 223, 246, 143, 202, 187, 187, 184, 223, 253, 224,
-162, 143, 202, 193, 143, 202, 194, 143, 202, 197, 224, 166, 224, 170, 224, 172,
-224, 175, 143, 202, 211, 143, 202, 215, 203, 210, 143, 202, 224, 143, 202, 227,
-224, 182, 224, 183, 181, 190, 184, 164, 190, 245, 143, 202, 242, 143, 202, 245,
-143, 202, 247, 224, 195, 198, 200, 224, 198, 143, 203, 162, 143, 203, 167, 224,
-200, 143, 203, 173, 143, 203, 177, 205, 177, 143, 203, 184, 143, 203, 185, 224,
-213, 189, 195, 143, 203, 199, 224, 217, 143, 203, 207, 143, 203, 210, 143, 203,
-215, 143, 203, 220, 143, 203, 225, 143, 203, 227, 178, 209, 143, 203, 236, 143,
-203, 240, 188, 238, 183, 190, 143, 203, 248, 184, 189, 206, 176, 143, 204, 168,
-143, 204, 170, 143, 204, 178, 143, 204, 182, 143, 204, 184, 143, 204, 189, 143,
-204, 192, 143, 204, 194, 143, 204, 199, 224, 247, 143, 204, 208, 143, 204, 213,
-224, 229, 143, 204, 226, 143, 204, 231, 143, 204, 234, 143, 204, 238, 143, 204,
-242, 143, 204, 245, 225, 166, 143, 204, 252, 143, 204, 254, 185, 249, 197, 188,
-225, 180, 197, 196, 196, 174, 225, 183, 143, 205, 180, 206, 177, 225, 191, 143,
-205, 187, 143, 205, 189, 143, 205, 196, 193, 193, 143, 205, 201, 225, 207, 225,
-215, 225, 214, 143, 205, 211, 225, 218, 143, 205, 216, 143, 205, 221, 143, 205,
-225, 225, 224, 143, 205, 231, 143, 205, 236, 143, 205, 242, 143, 205, 247, 225,
-240, 143, 206, 161, 143, 206, 167, 204, 254, 225, 245, 225, 252, 143, 206, 179,
-197, 208, 143, 206, 182, 187, 169, 226, 173, 143, 206, 193, 200, 233, 226, 176,
-226, 179, 143, 206, 205, 226, 181, 143, 206, 209, 226, 187, 196, 190, 189, 226,
-226, 190, 143, 206, 222, 143, 206, 228, 226, 197, 143, 206, 234, 143, 206, 239,
-143, 206, 243, 143, 206, 248, 143, 206, 253, 143, 207, 163, 143, 207, 168, 226,
-208, 226, 211, 143, 207, 176, 143, 207, 179, 143, 207, 182, 143, 207, 186, 226,
-218, 143, 207, 189, 143, 207, 192, 143, 207, 195, 182, 235, 192, 208, 186, 189,
-226, 230, 143, 207, 212, 181, 206, 203, 164, 185, 220, 143, 207, 225, 143, 207,
-228, 143, 207, 234, 200, 163, 226, 239, 226, 238, 200, 234, 143, 207, 244, 202,
-203, 143, 207, 252, 143, 208, 161, 226, 252, 200, 216, 227, 162, 143, 208, 173,
-176, 235, 143, 208, 185, 143, 208, 188, 143, 208, 190, 143, 208, 191, 143, 208,
-196, 143, 208, 200, 143, 208, 203, 143, 208, 207, 143, 208, 211, 227, 175, 190,
-205, 143, 208, 220, 143, 208, 223, 227, 180, 143, 208, 229, 143, 208, 235, 143,
-208, 238, 143, 208, 242, 143, 208, 244, 143, 208, 249, 143, 208, 252, 199, 233,
-190, 206, 176, 220, 143, 209, 172, 143, 209, 176, 143, 209, 178, 143, 209, 181,
-227, 202, 227, 203, 143, 209, 192, 178, 186, 143, 209, 198, 190, 247, 143, 209,
-206, 143, 209, 208, 143, 209, 211, 143, 209, 216, 143, 209, 219, 227, 221, 143,
-209, 223, 227, 227, 143, 209, 229, 227, 234, 227, 237, 143, 209, 234, 143, 209,
-239, 143, 209, 242, 181, 232, 143, 209, 244, 227, 250, 227, 252, 227, 247, 143,
-210, 163, 143, 210, 167, 195, 222, 228, 184, 228, 170, 228, 172, 143, 210, 180,
-143, 210, 182, 228, 176, 143, 210, 189, 143, 210, 191, 143, 210, 196, 200, 207,
-228, 189, 143, 210, 207, 198, 198, 143, 210, 212, 143, 210, 218, 143, 210, 224,
-228, 194, 143, 210, 231, 143, 210, 233, 143, 210, 237, 228, 213, 143, 210, 244,
-228, 216, 143, 210, 254, 143, 211, 164, 202, 198, 143, 211, 171, 143, 211, 173,
-206, 179, 143, 211, 176, 228, 234, 228, 236, 143, 211, 184, 143, 211, 187, 228,
-245, 228, 246, 143, 211, 199, 228, 250, 181, 234, 143, 211, 205, 143, 211, 209,
-229, 162, 143, 211, 215, 186, 217, 186, 176, 193, 200, 229, 174, 143, 211, 230,
-229, 179, 229, 177, 143, 211, 238, 143, 211, 243, 143, 211, 249, 143, 211, 252,
-229, 194, 188, 250, 143, 212, 166, 143, 212, 169, 143, 212, 174, 143, 212, 177,
-229, 206, 143, 212, 184, 143, 212, 187, 143, 212, 179, 229, 208, 143, 212, 194,
-229, 213, 203, 165, 229, 220, 143, 212, 206, 193, 161, 191, 165, 229, 229, 229,
-234, 143, 212, 221, 229, 239, 143, 212, 226, 143, 212, 229, 229, 251, 180, 204,
-143, 212, 240, 230, 163, 230, 169, 143, 212, 250, 143, 212, 254, 200, 237, 230,
-176, 230, 181, 143, 213, 171, 143, 213, 174, 143, 213, 178, 230, 192, 143, 213,
-183, 143, 213, 185, 143, 213, 187, 143, 213, 190, 143, 213, 194, 230, 203, 185,
-205, 143, 213, 203, 204, 215, 230, 212, 143, 213, 216, 204, 237, 143, 213, 226,
-230, 216, 192, 187, 143, 213, 228, 143, 213, 231, 191, 166, 143, 213, 234, 207,
-190, 190, 211, 184, 212, 143, 213, 241, 143, 213, 242, 176, 223, 143, 213, 245,
-143, 213, 250, 184, 213, 143, 213, 253, 182, 187, 187, 233, 143, 214, 170, 143,
-214, 175, 143, 214, 178, 196, 177, 143, 214, 183, 201, 229, 231, 181, 143, 214,
-193, 231, 171, 194, 220, 231, 174, 231, 178, 231, 177, 143, 214, 209, 231, 187,
-231, 190, 231, 193, 143, 214, 220, 143, 214, 224, 143, 214, 226, 143, 214, 231,
-143, 214, 236, 218, 170, 143, 214, 240, 143, 214, 244, 143, 214, 247, 143, 214,
-248, 231, 217, 143, 215, 161, 143, 215, 165, 143, 215, 167, 231, 226, 143, 215,
-171, 231, 232, 143, 215, 180, 143, 215, 184, 231, 236, 143, 215, 195, 203, 167,
-178, 234, 143, 215, 207, 143, 215, 209, 143, 215, 212, 143, 215, 216, 231, 249,
-231, 247, 183, 212, 232, 173, 143, 215, 233, 143, 215, 234, 195, 227, 232, 166,
-183, 213, 143, 215, 227, 143, 215, 253, 178, 174, 232, 174, 143, 216, 168, 143,
-216, 174, 143, 216, 176, 205, 233, 232, 207, 143, 216, 183, 143, 216, 187, 186,
-218, 143, 216, 191, 232, 203, 143, 216, 196, 143, 216, 198, 143, 216, 201, 232,
-206, 232, 212, 232, 226, 143, 216, 207, 143, 216, 212, 143, 216, 217, 198, 161,
-232, 211, 232, 216, 143, 216, 232, 190, 213, 143, 216, 236, 232, 231, 143, 216,
-240, 143, 216, 244, 143, 216, 247, 143, 216, 251, 143, 216, 254, 143, 217, 162,
-143, 217, 166, 143, 217, 171, 232, 209, 143, 217, 178, 177, 182, 143, 217, 183,
-143, 217, 188, 202, 195, 232, 254, 143, 217, 197, 143, 217, 201, 207, 207, 233,
-177, 143, 217, 216, 143, 217, 220, 177, 242, 143, 217, 228, 204, 244, 143, 217,
-232, 207, 206, 143, 217, 242, 233, 185, 143, 217, 247, 200, 205, 143, 217, 252,
-233, 193, 233, 190, 221, 177, 143, 218, 174, 205, 246, 143, 218, 178, 143, 218,
-183, 233, 200, 143, 218, 188, 143, 218, 193, 195, 238, 143, 218, 200, 143, 218,
-237, 233, 206, 143, 218, 210, 233, 219, 143, 218, 218, 143, 218, 222, 233, 217,
-233, 220, 233, 221, 233, 222, 194, 253, 203, 170, 233, 235, 195, 216, 143, 218,
-254, 143, 219, 162, 143, 219, 166, 143, 219, 172, 143, 219, 174, 233, 251, 143,
-219, 177, 233, 253, 233, 247, 234, 167, 143, 219, 192, 143, 219, 196, 234, 165,
-143, 219, 203, 205, 230, 234, 175, 143, 219, 214, 143, 219, 217, 143, 219, 222,
-143, 219, 226, 234, 187, 143, 219, 232, 143, 219, 237, 234, 192, 143, 219, 248,
-143, 219, 250, 234, 197, 143, 220, 164, 222, 167, 179, 185, 185, 213, 234, 206,
-234, 210, 182, 222, 194, 222, 194, 181, 143, 220, 190, 143, 220, 192, 184, 211,
-143, 220, 195, 143, 220, 197, 234, 227, 143, 220, 206, 234, 235, 234, 236, 234,
-233, 143, 220, 214, 179, 236, 143, 220, 222, 234, 243, 143, 220, 228, 143, 220,
-233, 234, 247, 143, 220, 240, 143, 220, 243, 235, 162, 143, 220, 250, 143, 220,
-254, 202, 164, 143, 221, 166, 179, 208, 143, 221, 173, 235, 178, 235, 180, 179,
-209, 235, 185, 191, 168, 143, 221, 189, 143, 221, 193, 143, 221, 197, 143, 221,
-199, 235, 194, 235, 196, 143, 221, 210, 191, 199, 143, 221, 217, 186, 190, 235,
-199, 143, 221, 229, 181, 205, 143, 221, 235, 235, 209, 143, 221, 243, 143, 221,
-248, 235, 216, 198, 201, 143, 222, 162, 235, 219, 180, 210, 207, 192, 235, 227,
-235, 221, 143, 222, 180, 143, 222, 183, 143, 222, 191, 235, 226, 143, 222, 189,
-235, 245, 235, 240, 235, 244, 143, 222, 201, 143, 222, 202, 201, 232, 183, 217,
-181, 196, 143, 222, 213, 218, 206, 143, 222, 221, 143, 222, 224, 195, 171, 236,
-175, 143, 222, 233, 236, 181, 190, 221, 208, 174, 143, 222, 250, 236, 186, 203,
-198, 236, 194, 185, 215, 192, 213, 236, 202, 178, 236, 194, 177, 143, 223, 178,
-199, 229, 188, 193, 143, 223, 187, 143, 223, 191, 143, 223, 194, 236, 219, 192,
-214, 143, 223, 201, 143, 223, 202, 177, 219, 143, 223, 209, 143, 223, 211, 143,
-223, 214, 143, 223, 218, 143, 223, 222, 143, 223, 227, 143, 223, 230, 236, 240,
-236, 238, 143, 223, 242, 236, 245, 236, 244, 143, 223, 250, 236, 247, 237, 169,
-236, 253, 143, 224, 171, 236, 254, 143, 224, 177, 143, 224, 181, 143, 224, 184,
-189, 179, 237, 175, 237, 179, 143, 224, 198, 237, 186, 191, 200, 143, 224, 209,
-143, 224, 212, 188, 214, 143, 224, 219, 198, 240, 237, 199, 143, 224, 225, 143,
-224, 230, 237, 210, 143, 224, 235, 143, 224, 239, 206, 216, 143, 224, 248, 237,
-217, 237, 219, 143, 225, 166, 143, 225, 170, 191, 201, 143, 225, 177, 237, 231,
-202, 213, 203, 248, 183, 222, 237, 233, 143, 225, 195, 143, 225, 197, 237, 254,
-143, 225, 203, 143, 225, 206, 237, 248, 194, 164, 143, 225, 212, 143, 225, 216,
-238, 167, 238, 166, 198, 187, 143, 225, 223, 143, 225, 226, 238, 175, 206, 203,
-237, 238, 205, 184, 143, 225, 241, 143, 225, 245, 238, 184, 143, 225, 251, 143,
-226, 163, 143, 226, 173, 143, 226, 169, 201, 244, 143, 226, 178, 143, 226, 179,
-143, 226, 185, 238, 192, 143, 226, 193, 143, 226, 199, 143, 226, 203, 143, 226,
-209, 143, 226, 212, 188, 242, 143, 226, 220, 189, 183, 185, 243, 143, 226, 228,
-238, 204, 143, 226, 237, 143, 226, 240, 238, 208, 238, 211, 143, 226, 254, 238,
-216, 143, 227, 164, 191, 203, 182, 252, 143, 227, 179, 143, 227, 182, 143, 227,
-187, 143, 227, 193, 143, 227, 198, 143, 227, 203, 143, 227, 207, 143, 227, 213,
-197, 180, 143, 227, 223, 143, 227, 226, 200, 173, 143, 227, 236, 143, 227, 242,
-189, 198, 143, 227, 251, 143, 227, 254, 143, 228, 164, 143, 228, 169, 238, 248,
-143, 228, 181, 143, 228, 188, 143, 228, 193, 143, 228, 200, 143, 228, 205, 181,
-248, 143, 228, 212, 143, 228, 214, 191, 238, 239, 162, 207, 163, 143, 228, 230,
-238, 253, 143, 228, 235, 143, 228, 241, 143, 228, 243, 239, 171, 143, 229, 161,
-143, 229, 167, 143, 229, 172, 143, 229, 176, 143, 229, 181, 143, 229, 183, 143,
-229, 188, 143, 229, 195, 239, 178, 182, 192, 143, 229, 207, 143, 229, 212, 143,
-229, 217, 143, 229, 222, 239, 197, 239, 195, 239, 196, 143, 229, 231, 143, 229,
-236, 143, 229, 238, 143, 229, 241, 239, 206, 239, 209, 239, 216, 196, 185, 239,
-217, 143, 230, 164, 239, 221, 239, 224, 143, 230, 173, 143, 230, 176, 239, 234,
-239, 235, 198, 174, 239, 243, 201, 236, 143, 230, 201, 143, 230, 203, 193, 203,
-239, 251, 143, 230, 214, 143, 230, 217, 240, 165, 198, 171, 143, 230, 224, 231,
-161, 240, 168, 143, 230, 233, 143, 230, 237, 143, 230, 240, 191, 253, 143, 230,
-242, 240, 186, 143, 230, 249, 143, 230, 250, 206, 237, 188, 251, 206, 238, 240,
-195, 143, 231, 167, 240, 199, 240, 201, 240, 205, 192, 196, 240, 208, 240, 211,
-240, 215, 143, 231, 191, 240, 217, 240, 223, 143, 231, 199, 240, 228, 202, 220,
-143, 231, 210, 240, 231, 143, 231, 223, 143, 231, 228, 143, 231, 235, 240, 236,
-143, 231, 240, 202, 199, 240, 243, 143, 231, 249, 143, 231, 252, 143, 232, 161,
-143, 232, 167, 143, 232, 170, 179, 220, 180, 234, 143, 232, 180, 143, 232, 185,
-201, 247, 143, 232, 190, 143, 232, 195, 143, 232, 199, 200, 244, 143, 232, 202,
-200, 211, 187, 244, 143, 232, 209, 143, 232, 211, 143, 232, 216, 143, 232, 220,
-143, 232, 223, 143, 232, 230, 241, 189, 241, 190, 143, 232, 242, 188, 243, 241,
-198, 143, 232, 251, 143, 233, 162, 194, 204, 195, 243, 143, 233, 170, 143, 233,
-173, 241, 209, 241, 211, 241, 215, 241, 214, 241, 217, 143, 233, 194, 143, 233,
-197, 241, 219, 143, 233, 204, 143, 233, 207, 241, 225, 241, 229, 241, 233, 185,
-252, 143, 233, 218, 241, 238, 143, 233, 228, 143, 233, 231, 143, 233, 236, 143,
-233, 240, 241, 249, 143, 233, 247, 143, 233, 254, 143, 234, 167, 242, 163, 242,
-166, 143, 234, 178, 143, 234, 182, 179, 161, 143, 234, 187, 143, 234, 189, 143,
-234, 194, 143, 234, 200, 143, 234, 205, 143, 234, 209, 143, 234, 215, 242, 184,
-143, 234, 223, 143, 234, 226, 143, 234, 230, 143, 234, 234, 242, 196, 143, 234,
-242, 194, 228, 143, 234, 247, 143, 234, 251, 143, 235, 161, 242, 218, 143, 235,
-168, 143, 235, 172, 143, 235, 177, 201, 201, 143, 235, 186, 143, 235, 188, 143,
-235, 194, 143, 235, 200, 143, 235, 205, 143, 235, 211, 242, 233, 196, 187, 242,
-236, 143, 235, 222, 178, 170, 143, 235, 225, 242, 245, 143, 235, 229, 143, 235,
-234, 242, 247, 243, 165, 177, 173, 143, 235, 248, 143, 235, 252, 143, 236, 163,
-143, 236, 167, 143, 236, 173, 143, 236, 175, 243, 170, 143, 236, 180, 143, 236,
-183, 143, 236, 186, 243, 186, 143, 236, 193, 143, 236, 198, 143, 236, 202, 243,
-191, 143, 236, 207, 143, 236, 210, 243, 193, 243, 195, 188, 175, 243, 200, 243,
-203, 206, 219, 243, 207, 143, 236, 238, 221, 224, 143, 236, 242, 185, 245, 243,
-217, 143, 236, 247, 143, 236, 252, 243, 228, 243, 231, 143, 237, 168, 143, 237,
-175, 143, 237, 178, 143, 237, 182, 201, 161, 143, 237, 194, 240, 237, 143, 237,
-202, 243, 245, 143, 237, 210, 143, 237, 214, 206, 182, 143, 237, 222, 143, 237,
-224, 161, 170, 161, 220, 163, 181, 161, 169, 163, 201, 163, 211, 161, 207, 163,
-231, 163, 241, 161, 208, 142, 165, 142, 175, 142, 185, 142, 195, 142, 205, 142,
-215, 161, 177
- });
-
- super.setUp();
- }
-
- @Override
- public void test_CodecDynamic () throws CharacterCodingException {
- encoder.onUnmappableCharacter(CodingErrorAction.REPORT);
- decoder.onMalformedInput(CodingErrorAction.REPORT);
- CharBuffer inputCB = CharBuffer.allocate(65536);
- for (int code = 32; code <= 65533; code ++) {
- if ((encoder.canEncode((char) code))
- && (code != 165) && (code != 8254) && (code != 63599)) {
- inputCB.put((char) code);
- }
- }
- inputCB.rewind();
- ByteBuffer intermediateBB = encoder.encode(inputCB);
- inputCB.rewind();
- intermediateBB.rewind();
- CharBuffer outputCB = decoder.decode(intermediateBB);
- outputCB.rewind();
- assertEqualCBs("decode(encode(A)) must be identical with A!",
- inputCB, outputCB);
- }
-
-}
diff --git a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
index b789ce3..e8790ea 100644
--- a/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
+++ b/luni/src/test/java/libcore/java/nio/charset/OldCharset_MultiByte_ISO_2022_JP.java
@@ -18,364 +18,16 @@
import java.nio.charset.CharacterCodingException;
public class OldCharset_MultiByte_ISO_2022_JP extends OldCharset_AbstractTest {
-
- @Override
- protected void setUp() throws Exception {
- charsetName = "ISO-2022-JP";
-
- testChars = theseChars(new int[]{
-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,
-162, 163, 165, 167, 168, 172, 176, 177, 180, 182, 215, 247, 913, 914, 924, 934,
-945, 955, 965, 1025, 1040, 1050, 1060, 1070, 1080, 1090, 1100, 8208, 8220, 8230, 8240, 8251,
-8451, 8491, 8592, 8658, 8704, 8715, 8730, 8743, 8756, 8786, 8800, 8810, 8834, 8869, 8978, 9472,
-9484, 9495, 9507, 9519, 9531, 9547, 9632, 9650, 9660, 9670, 9711, 9733, 9792, 9834, 12288, 12298,
-12308, 12353, 12363, 12373, 12383, 12393, 12403, 12413, 12423, 12433, 12443, 12453, 12463, 12473, 12483, 12493,
-12503, 12513, 12523, 12533, 19968, 19978, 19988, 19998, 20010, 20022, 20034, 20045, 20055, 20066, 20081, 20094,
-20104, 20114, 20124, 20134, 20144, 20154, 20164, 20174, 20184, 20195, 20205, 20215, 20225, 20237, 20250, 20271,
-20282, 20294, 20304, 20314, 20329, 20339, 20351, 20363, 20374, 20384, 20395, 20405, 20415, 20426, 20436, 20447,
-20462, 20472, 20485, 20495, 20505, 20515, 20525, 20537, 20547, 20559, 20570, 20581, 20594, 20605, 20621, 20632,
-20652, 20663, 20674, 20685, 20698, 20709, 20725, 20736, 20754, 20767, 20778, 20791, 20801, 20811, 20826, 20837,
-20849, 20860, 20870, 20880, 20896, 20906, 20916, 20932, 20950, 20960, 20970, 20981, 20992, 21002, 21012, 21028,
-21038, 21048, 21059, 21069, 21083, 21093, 21103, 21117, 21127, 21137, 21147, 21161, 21172, 21182, 21193, 21205,
-21215, 21234, 21246, 21256, 21269, 21280, 21290, 21304, 21315, 21325, 21335, 21350, 21360, 21371, 21398, 21408,
-21421, 21435, 21448, 21460, 21471, 21481, 21491, 21505, 21515, 21531, 21542, 21558, 21568, 21578, 21599, 21610,
-21621, 21632, 21643, 21666, 21676, 21688, 21698, 21720, 21730, 21741, 21754, 21764, 21775, 21806, 21816, 21828,
-21839, 21852, 21883, 21895, 21912, 21927, 21942, 21956, 21972, 21983, 22007, 22022, 22036, 22057, 22068, 22082,
-22092, 22107, 22120, 22132, 22144, 22154, 22164, 22176, 22190, 22204, 22216, 22227, 22238, 22254, 22265, 22275,
-22285, 22296, 22310, 22320, 22331, 22343, 22353, 22369, 22399, 22409, 22419, 22432, 22442, 22464, 22475, 22486,
-22496, 22516, 22528, 22538, 22549, 22561, 22575, 22586, 22602, 22612, 22622, 22633, 22645, 22659, 22675, 22687,
-22699, 22712, 22725, 22737, 22748, 22763, 22775, 22786, 22799, 22809, 22821, 22833, 22846, 22856, 22868, 22880,
-22890, 22900, 22913, 22925, 22937, 22947, 22962, 22974, 22985, 22995, 23013, 23030, 23041, 23057, 23068, 23081,
-23093, 23104, 23130, 23142, 23167, 23186, 23228, 23241, 23254, 23265, 23290, 23305, 23318, 23330, 23340, 23350,
-23360, 23376, 23386, 23396, 23408, 23418, 23429, 23439, 23449, 23459, 23470, 23480, 23490, 23500, 23515, 23525,
-23536, 23546, 23556, 23566, 23578, 23588, 23601, 23611, 23621, 23631, 23646, 23660, 23670, 23692, 23713, 23723,
-23734, 23749, 23769, 23784, 23798, 23815, 23825, 23835, 23849, 23883, 23900, 23913, 23923, 23938, 23948, 23965,
-23980, 23991, 24009, 24019, 24029, 24039, 24049, 24059, 24070, 24081, 24091, 24101, 24111, 24125, 24135, 24148,
-24159, 24178, 24188, 24199, 24213, 24224, 24235, 24245, 24257, 24271, 24282, 24296, 24307, 24318, 24329, 24339,
-24351, 24361, 24373, 24385, 24396, 24406, 24417, 24427, 24439, 24449, 24459, 24471, 24481, 24493, 24505, 24515,
-24525, 24535, 24548, 24560, 24571, 24590, 24601, 24613, 24623, 24634, 24646, 24656, 24666, 24676, 24687, 24705,
-24715, 24726, 24736, 24746, 24756, 24773, 24785, 24796, 24807, 24817, 24827, 24838, 24853, 24863, 24876, 24892,
-24903, 24915, 24925, 24935, 24945, 24958, 24970, 24980, 24996, 25006, 25018, 25030, 25040, 25059, 25074, 25084,
-25096, 25106, 25117, 25130, 25140, 25151, 25161, 25171, 25182, 25192, 25206, 25216, 25226, 25236, 25246, 25259,
-25269, 25282, 25292, 25303, 25313, 25324, 25334, 25345, 25356, 25369, 25383, 25402, 25417, 25429, 25447, 25458,
-25472, 25484, 25494, 25504, 25514, 25524, 25534, 25545, 25558, 25569, 25582, 25594, 25606, 25619, 25638, 25652,
-25662, 25678, 25688, 25703, 25718, 25731, 25746, 25758, 25769, 25785, 25797, 25810, 25824, 25836, 25846, 25856,
-25880, 25891, 25903, 25913, 25925, 25935, 25945, 25955, 25968, 25986, 25996, 26007, 26017, 26027, 26039, 26049,
-26059, 26071, 26081, 26092, 26106, 26118, 26131, 26143, 26157, 26172, 26185, 26205, 26215, 26228, 26241, 26254,
-26264, 26274, 26286, 26296, 26308, 26326, 26336, 26352, 26364, 26376, 26388, 26398, 26408, 26420, 26431, 26441,
-26451, 26462, 26474, 26485, 26495, 26505, 26517, 26528, 26543, 26553, 26564, 26574, 26584, 26594, 26604, 26619,
-26643, 26654, 26665, 26676, 26688, 26701, 26713, 26723, 26740, 26750, 26765, 26775, 26786, 26797, 26809, 26820,
-26834, 26847, 26862, 26873, 26884, 26894, 26905, 26915, 26928, 26941, 26954, 26964, 26974, 26986, 26996, 27006,
-27018, 27028, 27040, 27054, 27067, 27079, 27091, 27101, 27111, 27122, 27133, 27146, 27156, 27166, 27177, 27189,
-27204, 27224, 27234, 27250, 27263, 27277, 27287, 27298, 27308, 27320, 27330, 27345, 27355, 27368, 27386, 27396,
-27410, 27421, 27431, 27442, 27453, 27463, 27475, 27487, 27497, 27507, 27519, 27529, 27541, 27556, 27567, 27578,
-27589, 27602, 27615, 27627, 27656, 27667, 27683, 27700, 27710, 27726, 27738, 27752, 27762, 27773, 27784, 27794,
-27809, 27819, 27832, 27844, 27859, 27869, 27880, 27891, 27915, 27927, 27941, 27954, 27965, 27993, 28003, 28014,
-28024, 28037, 28051, 28079, 28092, 28102, 28113, 28126, 28136, 28147, 28165, 28179, 28189, 28201, 28216, 28227,
-28237, 28248, 28263, 28274, 28286, 28300, 28310, 28322, 28335, 28346, 28356, 28369, 28381, 28396, 28407, 28417,
-28431, 28448, 28459, 28472, 28485, 28500, 28511, 28525, 28536, 28546, 28558, 28577, 28593, 28608, 28628, 28639,
-28651, 28662, 28673, 28683, 28693, 28703, 28716, 28734, 28748, 28760, 28771, 28783, 28796, 28809, 28825, 28844,
-28856, 28872, 28889, 28913, 28925, 28937, 28948, 28961, 28982, 29001, 29013, 29026, 29036, 29053, 29064, 29076,
-29087, 29100, 29113, 29123, 29134, 29151, 29164, 29177, 29190, 29200, 29211, 29224, 29234, 29244, 29254, 29266,
-29277, 29287, 29298, 29309, 29319, 29330, 29344, 29356, 29366, 29378, 29390, 29401, 29417, 29431, 29450, 29462,
-29477, 29487, 29502, 29518, 29539, 29552, 29562, 29572, 29590, 29609, 29619, 29632, 29642, 29662, 29674, 29688,
-29699, 29730, 29746, 29759, 29781, 29791, 29801, 29811, 29822, 29835, 29854, 29872, 29885, 29898, 29908, 29920,
-29934, 29944, 29955, 29965, 29976, 29987, 30000, 30010, 30020, 30031, 30041, 30052, 30064, 30079, 30089, 30100,
-30115, 30129, 30140, 30151, 30162, 30174, 30185, 30195, 30206, 30217, 30239, 30256, 30267, 30278, 30290, 30300,
-30311, 30322, 30332, 30342, 30352, 30362, 30382, 30392, 30402, 30413, 30423, 30433, 30446, 30456, 30468, 30491,
-30501, 30519, 30535, 30554, 30565, 30585, 30603, 30622, 30636, 30646, 30663, 30679, 30690, 30701, 30716, 30732,
-30752, 30770, 30783, 30813, 30827, 30844, 30854, 30865, 30883, 30895, 30906, 30917, 30928, 30938, 30951, 30964,
-30977, 30990, 31001, 31014, 31034, 31047, 31059, 31069, 31080, 31095, 31105, 31117, 31133, 31143, 31155, 31165,
-31177, 31189, 31199, 31209, 31227, 31240, 31252, 31263, 31278, 31291, 31302, 31312, 31329, 31339, 31350, 31361,
-31378, 31391, 31401, 31414, 31427, 31437, 31449, 31459, 31469, 31480, 31490, 31503, 31513, 31525, 31539, 31557,
-31567, 31581, 31591, 31601, 31622, 31634, 31644, 31658, 31668, 31680, 31691, 31709, 31721, 31731, 31744, 31757,
-31767, 31777, 31787, 31799, 31811, 31821, 31832, 31844, 31859, 31870, 31881, 31893, 31903, 31915, 31929, 31941,
-31954, 31964, 31975, 31986, 31998, 32010, 32020, 32032, 32043, 32053, 32063, 32075, 32086, 32097, 32110, 32121,
-32137, 32147, 32159, 32171, 32181, 32191, 32202, 32213, 32224, 32236, 32251, 32261, 32274, 32286, 32299, 32309,
-32321, 32331, 32341, 32358, 32368, 32379, 32392, 32402, 32412, 32566, 32581, 32592, 32607, 32617, 32629, 32642,
-32652, 32666, 32676, 32686, 32696, 32709, 32722, 32736, 32747, 32761, 32771, 32784, 32796, 32808, 32819, 32829,
-32842, 32854, 32865, 32879, 32889, 32900, 32915, 32925, 32937, 32948, 32963, 32974, 32985, 32996, 33007, 33020,
-33030, 33050, 33065, 33075, 33086, 33099, 33109, 33119, 33131, 33144, 33154, 33167, 33178, 33188, 33200, 33210,
-33222, 33233, 33247, 33258, 33268, 33278, 33288, 33298, 33308, 33321, 33331, 33344, 33368, 33378, 33390, 33400,
-33419, 33433, 33445, 33455, 33465, 33477, 33489, 33499, 33509, 33521, 33531, 33541, 33558, 33571, 33583, 33593,
-33605, 33615, 33651, 33669, 33683, 33694, 33704, 33717, 33729, 33740, 33750, 33760, 33771, 33783, 33795, 33805,
-33824, 33834, 33845, 33862, 33879, 33889, 33899, 33909, 33922, 33936, 33948, 33965, 33976, 33988, 34000, 34010,
-34028, 34044, 34054, 34065, 34079, 34092, 34109, 34120, 34133, 34147, 34157, 34167, 34180, 34192, 34203, 34214,
-34233, 34249, 34261, 34276, 34295, 34306, 34323, 34338, 34349, 34367, 34381, 34394, 34407, 34417, 34427, 34442,
-34453, 34467, 34479, 34500, 34510, 34521, 34532, 34542, 34552, 34562, 34573, 34584, 34597, 34612, 34623, 34633,
-34643, 34655, 34666, 34676, 34687, 34701, 34719, 34731, 34746, 34756, 34768, 34784, 34799, 34809, 34821, 34831,
-34849, 34865, 34875, 34886, 34898, 34909, 34920, 34930, 34941, 34952, 34962, 34974, 34987, 34997, 35007, 35023,
-35033, 35048, 35058, 35068, 35079, 35090, 35101, 35114, 35126, 35137, 35148, 35158, 35168, 35178, 35188, 35198,
-35208, 35219, 35233, 35244, 35258, 35282, 35292, 35302, 35316, 35328, 35338, 35350, 35363, 35373, 35386, 35398,
-35408, 35419, 35430, 35440, 35452, 35463, 35473, 35486, 35496, 35506, 35516, 35527, 35538, 35548, 35558, 35569,
-35582, 35596, 35606, 35616, 35627, 35641, 35657, 35670, 35686, 35696, 35709, 35722, 35734, 35895, 35905, 35916,
-35930, 35946, 35960, 35970, 35980, 35992, 36002, 36012, 36022, 36032, 36042, 36058, 36068, 36090, 36100, 36111,
-36196, 36208, 36225, 36249, 36259, 36275, 36286, 36299, 36310, 36321, 36331, 36341, 36351, 36361, 36381, 36394,
-36404, 36418, 36428, 36441, 36451, 36466, 36476, 36487, 36497, 36513, 36523, 36542, 36552, 36562, 36575, 36587,
-36600, 36611, 36626, 36636, 36646, 36659, 36670, 36681, 36695, 36705, 36763, 36775, 36785, 36795, 36805, 36817,
-36834, 36845, 36855, 36865, 36875, 36885, 36895, 36910, 36920, 36930, 36941, 36952, 36963, 36973, 36983, 36993,
-37007, 37027, 37039, 37057, 37070, 37083, 37096, 37109, 37122, 37138, 37165, 37193, 37204, 37218, 37228, 37239,
-37250, 37261, 37271, 37282, 37295, 37306, 37318, 37328, 37339, 37350, 37365, 37375, 37389, 37406, 37417, 37428,
-37439, 37449, 37463, 37474, 37489, 37502, 37521, 37531, 37549, 37559, 37583, 37604, 37618, 37628, 37638, 37648,
-37658, 37670, 37682, 37700, 37716, 37728, 37740, 37756, 37772, 37782, 37799, 37817, 37827, 37840, 37853, 37864,
-37891, 37904, 37914, 37931, 37941, 37953, 37969, 37979, 37994, 38005, 38015, 38263, 38274, 38287, 38297, 38307,
-38317, 38329, 38339, 38349, 38360, 38370, 38428, 38440, 38450, 38463, 38475, 38491, 38501, 38512, 38522, 38533,
-38543, 38553, 38563, 38576, 38587, 38597, 38609, 38619, 38632, 38642, 38656, 38666, 38678, 38692, 38704, 38717,
-38728, 38738, 38748, 38758, 38769, 38780, 38790, 38800, 38812, 38822, 38835, 38851, 38867, 38893, 38907, 38917,
-38927, 38938, 38948, 38964, 38982, 38996, 39006, 39019, 39080, 39094, 39107, 39131, 39145, 39156, 39166, 39177,
-39187, 39197, 39208, 39229, 39241, 39253, 39318, 39333, 39347, 39361, 39376, 39387, 39405, 39416, 39429, 39439,
-39449, 39464, 39479, 39490, 39501, 39511, 39522, 39592, 39608, 39620, 39631, 39646, 39658, 39668, 39686, 39704,
-39714, 39726, 39739, 39749, 39759, 39770, 39791, 39811, 39822, 39839, 39850, 39860, 39872, 39882, 39892, 39905,
-39920, 39940, 39952, 39963, 39973, 39983, 39993, 40006, 40018, 40032, 40054, 40165, 40176, 40195, 40206, 40219,
-40230, 40251, 40262, 40272, 40284, 40300, 40314, 40327, 40346, 40356, 40367, 40378, 40388, 40399, 40409, 40422,
-40434, 40445, 40474, 40565, 40575, 40587, 40597, 40607, 40617, 40632, 40644, 40654, 40664, 40677, 40687, 40697,
-40711, 40723, 40736, 40748, 40763, 40778, 40788, 40799, 40810, 40822, 40845, 40860, 65281, 65291, 65301, 65311,
-65321, 65331, 65341, 65351, 65361, 65371, 65381, 65391, 65401, 65411, 65421, 65431, 65507
- });
-
- testBytes = theseBytes(new int[]{
-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,
-27, 36, 66, 33, 113, 33, 114, 27, 40, 74, 92, 27, 36, 66, 33, 120,
-33, 47, 34, 76, 33, 107, 33, 94, 33, 45, 34, 121, 33, 95, 33, 96,
-38, 33, 38, 34, 38, 44, 38, 53, 38, 65, 38, 75, 38, 84, 39, 39,
-39, 33, 39, 44, 39, 54, 39, 64, 39, 90, 39, 100, 39, 110, 33, 62,
-33, 72, 33, 68, 34, 115, 34, 40, 33, 110, 34, 114, 34, 43, 34, 77,
-34, 79, 34, 59, 34, 101, 34, 74, 33, 104, 34, 98, 33, 98, 34, 99,
-34, 62, 34, 93, 34, 94, 40, 33, 40, 35, 40, 49, 40, 50, 40, 56,
-40, 53, 40, 54, 34, 35, 34, 37, 34, 39, 34, 33, 34, 126, 33, 122,
-33, 106, 34, 118, 33, 33, 33, 84, 33, 76, 36, 33, 36, 43, 36, 53,
-36, 63, 36, 73, 36, 83, 36, 93, 36, 103, 36, 113, 33, 43, 37, 37,
-37, 47, 37, 57, 37, 67, 37, 77, 37, 87, 37, 97, 37, 107, 37, 117,
-48, 108, 62, 101, 51, 110, 62, 103, 80, 36, 80, 38, 80, 41, 70, 99,
-62, 104, 86, 38, 77, 112, 52, 37, 77, 61, 56, 95, 48, 33, 75, 114,
-80, 55, 63, 77, 80, 60, 80, 58, 73, 85, 66, 101, 80, 65, 80, 67,
-52, 107, 56, 96, 50, 113, 71, 108, 59, 71, 67, 34, 58, 52, 80, 69,
-80, 80, 50, 66, 59, 72, 78, 99, 80, 85, 54, 34, 85, 37, 63, 47,
-74, 88, 61, 83, 80, 87, 80, 88, 61, 36, 74, 112, 80, 102, 96, 71,
-56, 117, 74, 111, 79, 65, 55, 112, 80, 112, 74, 80, 80, 118, 55, 114,
-60, 69, 53, 54, 75, 53, 59, 49, 58, 69, 61, 125, 81, 36, 70, 47,
-78, 61, 81, 39, 81, 44, 53, 55, 60, 116, 61, 126, 77, 37, 81, 54,
-48, 116, 57, 110, 69, 94, 70, 126, 54, 38, 55, 115, 49, 95, 102, 110,
-52, 39, 81, 81, 58, 99, 64, 40, 82, 69, 81, 92, 70, 100, 81, 97,
-69, 97, 52, 41, 81, 101, 72, 61, 81, 105, 55, 116, 68, 102, 65, 48,
-57, 100, 71, 109, 73, 123, 81, 119, 55, 96, 81, 125, 78, 79, 61, 117,
-79, 43, 51, 47, 74, 89, 70, 48, 74, 103, 55, 46, 56, 123, 82, 51,
-82, 56, 62, 34, 72, 91, 82, 62, 64, 105, 82, 68, 70, 110, 55, 53,
-48, 117, 82, 74, 82, 77, 82, 78, 49, 94, 53, 110, 75, 116, 61, 71,
-82, 87, 67, 33, 49, 38, 82, 94, 49, 37, 55, 47, 72, 93, 82, 101,
-82, 96, 57, 112, 82, 108, 60, 118, 82, 106, 82, 114, 58, 112, 82, 120,
-82, 123, 82, 121, 83, 34, 83, 38, 83, 47, 83, 45, 83, 46, 49, 52,
-83, 41, 83, 52, 83, 57, 66, 111, 76, 100, 83, 53, 83, 65, 83, 73,
-83, 67, 55, 118, 49, 68, 83, 78, 83, 81, 83, 77, 83, 83, 67, 50,
-83, 82, 50, 94, 83, 92, 49, 61, 65, 57, 51, 122, 52, 111, 74, 46,
-83, 102, 83, 103, 83, 105, 83, 104, 83, 108, 83, 112, 83, 116, 83, 119,
-50, 115, 83, 121, 83, 122, 74, 96, 84, 35, 84, 37, 84, 41, 67, 79,
-84, 45, 54, 81, 57, 35, 84, 51, 84, 52, 84, 53, 84, 54, 84, 55,
-84, 58, 84, 49, 75, 100, 84, 66, 73, 86, 62, 125, 75, 89, 84, 65,
-66, 68, 84, 72, 116, 33, 58, 102, 50, 116, 69, 99, 58, 73, 49, 118,
-63, 80, 54, 45, 74, 104, 84, 82, 84, 83, 84, 87, 84, 89, 84, 91,
-84, 96, 59, 78, 68, 91, 84, 105, 50, 70, 61, 72, 84, 110, 60, 58,
-84, 115, 70, 96, 75, 91, 84, 123, 67, 37, 69, 91, 85, 34, 85, 43,
-76, 47, 85, 38, 85, 39, 62, 42, 59, 80, 64, 43, 49, 56, 48, 40,
-48, 82, 85, 48, 85, 49, 74, 90, 85, 55, 85, 52, 58, 39, 73, 88,
-76, 59, 71, 94, 85, 60, 60, 59, 85, 69, 67, 100, 85, 70, 52, 114,
-85, 74, 62, 110, 68, 92, 85, 78, 85, 82, 59, 82, 85, 85, 56, 73,
-85, 89, 85, 94, 66, 112, 57, 40, 67, 104, 64, 107, 53, 92, 85, 98,
-60, 100, 73, 89, 52, 50, 85, 108, 85, 110, 59, 123, 60, 77, 70, 51,
-62, 48, 76, 96, 61, 34, 63, 44, 53, 111, 86, 34, 66, 48, 86, 36,
-86, 39, 86, 41, 50, 44, 86, 45, 86, 47, 86, 50, 86, 53, 50, 101,
-69, 103, 63, 114, 86, 66, 86, 65, 74, 120, 86, 75, 86, 63, 63, 115,
-86, 77, 86, 81, 86, 58, 86, 83, 86, 84, 86, 88, 86, 90, 86, 92,
-64, 110, 57, 42, 56, 74, 52, 44, 72, 65, 86, 102, 86, 103, 63, 99,
-66, 83, 75, 57, 86, 115, 86, 111, 86, 112, 52, 51, 77, 68, 72, 95,
-68, 108, 86, 121, 56, 75, 48, 67, 86, 122, 86, 126, 87, 36, 87, 40,
-87, 44, 87, 48, 87, 50, 53, 93, 68, 111, 87, 56, 68, 37, 87, 59,
-87, 61, 87, 65, 87, 68, 68, 38, 87, 71, 64, 44, 78, 39, 70, 64,
-56, 102, 87, 84, 69, 48, 63, 52, 71, 38, 59, 86, 87, 88, 88, 45,
-87, 87, 87, 99, 87, 96, 53, 94, 54, 49, 87, 106, 87, 113, 54, 50,
-87, 107, 87, 117, 66, 41, 87, 122, 88, 39, 88, 35, 77, 42, 48, 45,
-88, 44, 62, 112, 79, 71, 64, 75, 87, 124, 88, 61, 88, 60, 88, 52,
-88, 51, 52, 54, 88, 71, 88, 70, 88, 64, 88, 88, 88, 87, 55, 69,
-88, 85, 77, 93, 88, 96, 88, 94, 74, 48, 88, 99, 88, 107, 88, 106,
-50, 123, 88, 112, 68, 40, 88, 118, 88, 121, 50, 124, 108, 67, 89, 35,
-66, 87, 75, 60, 72, 98, 66, 71, 89, 42, 89, 46, 73, 94, 53, 59,
-71, 68, 89, 56, 66, 114, 72, 100, 68, 113, 89, 68, 89, 66, 89, 57,
-51, 72, 51, 103, 59, 34, 59, 125, 89, 72, 53, 115, 89, 75, 68, 114,
-66, 42, 74, 97, 74, 123, 55, 126, 89, 87, 62, 56, 89, 85, 78, 43,
-65, 60, 68, 79, 89, 97, 89, 102, 77, 44, 48, 46, 52, 120, 77, 73,
-89, 108, 89, 109, 89, 110, 89, 107, 58, 113, 89, 119, 69, 38, 89, 116,
-89, 118, 55, 98, 59, 53, 70, 53, 89, 124, 51, 73, 90, 35, 90, 34,
-90, 43, 53, 60, 90, 49, 90, 53, 90, 55, 90, 59, 59, 89, 50, 126,
-56, 78, 73, 82, 54, 53, 59, 54, 63, 116, 90, 76, 73, 76, 69, 77,
-48, 54, 90, 81, 90, 82, 90, 85, 64, 123, 52, 122, 90, 92, 61, 92,
-50, 34, 58, 43, 48, 87, 64, 49, 62, 60, 67, 107, 90, 105, 90, 108,
-90, 110, 64, 50, 54, 71, 90, 117, 90, 120, 68, 42, 74, 107, 91, 34,
-91, 33, 91, 35, 91, 37, 91, 41, 82, 88, 55, 110, 58, 115, 91, 46,
-76, 90, 75, 81, 91, 51, 63, 121, 60, 93, 91, 57, 91, 66, 53, 79,
-72, 68, 91, 62, 75, 109, 79, 72, 56, 79, 91, 84, 74, 65, 91, 85,
-68, 83, 91, 82, 91, 75, 58, 58, 64, 114, 91, 89, 91, 91, 64, 115,
-91, 92, 91, 93, 91, 98, 91, 99, 91, 111, 91, 117, 91, 116, 57, 60,
-62, 63, 91, 104, 91, 110, 52, 126, 75, 64, 69, 111, 63, 57, 92, 42,
-92, 38, 68, 71, 63, 122, 92, 48, 92, 63, 92, 61, 77, 76, 92, 56,
-92, 65, 92, 68, 92, 60, 92, 57, 58, 103, 79, 49, 92, 85, 92, 70,
-92, 80, 116, 34, 92, 74, 92, 79, 92, 97, 92, 96, 65, 101, 92, 104,
-92, 102, 92, 100, 56, 34, 62, 65, 92, 109, 53, 76, 92, 115, 92, 111,
-51, 96, 92, 122, 93, 33, 92, 125, 93, 40, 93, 38, 93, 37, 93, 42,
-54, 123, 72, 39, 93, 50, 77, 115, 93, 51, 49, 53, 50, 36, 77, 95,
-54, 86, 93, 60, 52, 63, 93, 67, 74, 98, 58, 80, 93, 71, 61, 94,
-93, 77, 93, 79, 93, 82, 59, 38, 53, 35, 70, 71, 93, 91, 93, 93,
-93, 97, 93, 98, 93, 102, 63, 101, 72, 69, 72, 70, 49, 120, 93, 113,
-53, 98, 53, 37, 68, 64, 93, 115, 75, 87, 75, 119, 74, 40, 93, 117,
-93, 119, 93, 123, 67, 109, 49, 75, 77, 78, 64, 118, 68, 69, 61, 39,
-94, 42, 94, 54, 94, 49, 73, 98, 63, 59, 94, 58, 94, 50, 51, 54,
-78, 67, 94, 66, 61, 74, 94, 68, 94, 70, 61, 95, 64, 54, 55, 76,
-94, 97, 50, 57, 94, 98, 94, 92, 94, 90, 62, 69, 77, 47, 94, 83,
-79, 81, 72, 46, 61, 96, 48, 110, 94, 106, 69, 46, 94, 107, 51, 106,
-66, 108, 94, 118, 95, 35, 53, 121, 79, 51, 71, 121, 76, 33, 65, 50,
-52, 67, 55, 105, 51, 99, 95, 44, 95, 38, 95, 45, 95, 48, 95, 54,
-69, 67, 55, 99, 95, 62, 95, 59, 77, 116, 111, 105, 95, 71, 95, 68,
-73, 78, 95, 79, 64, 37, 95, 81, 94, 117, 70, 103, 95, 84, 69, 116,
-60, 94, 79, 39, 95, 85, 95, 89, 95, 90, 78, 117, 95, 96, 95, 88,
-95, 98, 95, 97, 49, 107, 76, 53, 65, 51, 78, 123, 95, 102, 95, 105,
-95, 108, 64, 122, 95, 103, 77, 80, 61, 79, 95, 114, 95, 116, 71, 51,
-95, 121, 83, 91, 95, 123, 96, 33, 71, 122, 96, 36, 96, 37, 96, 38,
-96, 42, 96, 44, 96, 47, 68, 45, 76, 70, 75, 82, 64, 55, 56, 35,
-96, 54, 96, 55, 53, 62, 56, 36, 62, 117, 54, 56, 96, 64, 65, 64,
-60, 109, 96, 70, 96, 73, 96, 75, 96, 80, 96, 78, 96, 81, 96, 82,
-61, 67, 96, 88, 96, 92, 56, 60, 54, 106, 52, 97, 96, 94, 96, 97,
-59, 57, 96, 100, 55, 62, 96, 105, 53, 101, 66, 118, 96, 106, 96, 109,
-96, 108, 96, 110, 96, 114, 58, 60, 96, 119, 96, 120, 96, 121, 52, 68,
-60, 37, 96, 123, 96, 125, 97, 33, 97, 37, 97, 41, 97, 44, 97, 48,
-52, 69, 59, 58, 69, 68, 68, 46, 97, 55, 48, 90, 78, 49, 97, 63,
-48, 91, 53, 38, 97, 73, 97, 75, 97, 79, 97, 87, 97, 86, 62, 73,
-97, 90, 97, 93, 65, 105, 97, 101, 97, 94, 97, 104, 97, 105, 97, 112,
-97, 113, 97, 116, 76, 126, 97, 117, 97, 124, 98, 33, 98, 36, 51, 39,
-59, 41, 98, 45, 72, 105, 98, 48, 98, 51, 98, 52, 69, 112, 98, 56,
-76, 92, 65, 106, 98, 64, 98, 70, 98, 68, 98, 71, 98, 73, 98, 74,
-98, 78, 98, 81, 98, 83, 98, 86, 61, 86, 98, 88, 98, 94, 98, 96,
-76, 112, 67, 59, 98, 101, 98, 102, 98, 105, 75, 36, 57, 92, 62, 75,
-78, 50, 98, 111, 98, 110, 72, 106, 98, 114, 98, 117, 51, 78, 98, 124,
-72, 88, 99, 34, 99, 33, 99, 36, 62, 76, 65, 67, 99, 40, 98, 104,
-60, 40, 53, 64, 99, 49, 61, 75, 73, 60, 69, 120, 54, 88, 50, 82,
-99, 53, 99, 54, 99, 58, 54, 89, 99, 61, 99, 62, 65, 69, 67, 97,
-48, 92, 99, 67, 76, 45, 99, 72, 60, 111, 99, 75, 75, 84, 48, 44,
-99, 81, 51, 79, 53, 102, 70, 77, 67, 98, 55, 34, 99, 93, 99, 96,
-51, 118, 99, 103, 99, 107, 61, 87, 99, 113, 81, 63, 99, 115, 99, 116,
-99, 121, 63, 90, 99, 119, 100, 38, 72, 53, 100, 56, 100, 42, 100, 44,
-74, 79, 100, 54, 100, 51, 67, 61, 100, 62, 64, 97, 100, 58, 100, 64,
-100, 65, 100, 74, 100, 71, 100, 77, 100, 76, 52, 74, 100, 84, 100, 83,
-100, 87, 64, 82, 100, 92, 100, 94, 74, 70, 76, 98, 74, 52, 71, 116,
-48, 64, 100, 104, 100, 111, 100, 114, 100, 117, 100, 118, 78, 72, 100, 122,
-53, 106, 101, 36, 61, 99, 65, 71, 59, 103, 101, 42, 101, 41, 101, 38,
-101, 45, 77, 109, 101, 49, 56, 40, 101, 53, 101, 52, 101, 70, 101, 64,
-101, 61, 76, 74, 54, 91, 101, 110, 68, 121, 76, 75, 101, 76, 101, 79,
-101, 83, 60, 74, 75, 37, 101, 92, 72, 75, 55, 82, 65, 54, 101, 90,
-55, 43, 101, 108, 101, 114, 101, 117, 101, 124, 52, 76, 102, 33, 102, 37,
-102, 42, 102, 45, 71, 77, 102, 48, 102, 53, 102, 57, 55, 50, 102, 62,
-102, 64, 102, 66, 61, 44, 63, 105, 52, 101, 102, 75, 57, 77, 66, 81,
-102, 83, 102, 85, 60, 42, 67, 63, 102, 88, 64, 59, 65, 111, 78, 126,
-102, 100, 102, 103, 102, 107, 52, 78, 56, 42, 58, 104, 48, 95, 66, 91,
-102, 114, 48, 125, 102, 120, 103, 38, 64, 72, 53, 83, 102, 123, 71, 62,
-103, 35, 102, 126, 79, 83, 103, 53, 60, 112, 68, 50, 103, 48, 57, 81,
-73, 102, 103, 51, 103, 56, 103, 63, 50, 50, 103, 66, 103, 71, 60, 43,
-67, 87, 103, 76, 54, 61, 80, 48, 61, 88, 103, 85, 103, 88, 103, 89,
-103, 91, 103, 96, 58, 49, 103, 103, 48, 114, 73, 103, 51, 41, 63, 68,
-54, 92, 52, 35, 49, 113, 50, 87, 60, 99, 49, 81, 103, 120, 51, 125,
-104, 35, 104, 52, 104, 42, 104, 39, 104, 41, 49, 65, 104, 58, 104, 46,
-103, 118, 52, 80, 104, 62, 104, 57, 104, 71, 54, 93, 62, 84, 104, 74,
-104, 65, 104, 72, 104, 68, 104, 76, 104, 78, 104, 84, 104, 98, 104, 94,
-67, 120, 73, 114, 104, 89, 48, 42, 104, 92, 61, 47, 73, 71, 104, 90,
-62, 120, 67, 95, 104, 108, 104, 107, 75, 41, 104, 122, 104, 81, 74, 78,
-104, 119, 104, 118, 74, 67, 104, 126, 105, 36, 104, 124, 105, 43, 105, 49,
-71, 118, 105, 51, 105, 45, 65, 38, 105, 55, 105, 52, 105, 57, 70, 35,
-61, 115, 105, 34, 105, 63, 105, 68, 77, 118, 105, 71, 105, 72, 53, 117,
-105, 76, 105, 77, 48, 58, 50, 99, 59, 61, 105, 79, 105, 85, 105, 86,
-51, 66, 51, 63, 72, 58, 72, 90, 66, 125, 75, 42, 105, 107, 67, 88,
-105, 114, 105, 110, 105, 111, 64, 102, 106, 33, 105, 118, 106, 35, 105, 122,
-71, 104, 77, 59, 106, 38, 106, 46, 77, 102, 106, 47, 106, 44, 106, 54,
-106, 52, 51, 42, 106, 36, 106, 55, 106, 66, 106, 67, 106, 71, 61, 48,
-106, 74, 62, 87, 73, 61, 106, 85, 106, 83, 55, 54, 106, 88, 106, 81,
-72, 111, 106, 84, 106, 95, 78, 34, 106, 101, 106, 107, 106, 108, 106, 105,
-74, 35, 75, 43, 106, 124, 106, 116, 106, 121, 106, 118, 106, 123, 50, 40,
-106, 125, 107, 36, 107, 38, 107, 40, 107, 42, 107, 44, 107, 46, 107, 49,
-107, 52, 51, 81, 107, 57, 63, 40, 107, 60, 56, 64, 63, 86, 107, 63,
-55, 109, 64, 95, 63, 71, 107, 73, 58, 62, 107, 71, 59, 110, 53, 77,
-107, 75, 56, 88, 107, 84, 56, 108, 107, 82, 50, 93, 53, 67, 67, 76,
-78, 74, 68, 53, 68, 124, 107, 97, 66, 122, 107, 104, 107, 108, 107, 111,
-107, 115, 54, 96, 107, 122, 107, 123, 55, 89, 53, 68, 108, 37, 90, 78,
-108, 43, 67, 43, 108, 47, 108, 50, 70, 90, 57, 107, 108, 56, 108, 58,
-75, 70, 108, 66, 57, 87, 64, 85, 108, 74, 50, 108, 66, 49, 108, 79,
-108, 77, 108, 81, 108, 83, 108, 87, 64, 86, 65, 118, 108, 99, 108, 100,
-60, 113, 66, 45, 108, 102, 108, 109, 108, 106, 64, 87, 108, 111, 65, 41,
-108, 117, 108, 116, 108, 118, 109, 41, 108, 125, 108, 122, 109, 35, 109, 38,
-109, 42, 109, 45, 109, 46, 109, 48, 109, 54, 109, 58, 63, 72, 109, 63,
-109, 65, 56, 46, 70, 112, 109, 71, 60, 52, 51, 83, 109, 76, 109, 79,
-109, 83, 109, 84, 109, 89, 109, 91, 109, 94, 55, 37, 63, 73, 82, 33,
-63, 43, 68, 84, 63, 87, 54, 97, 109, 107, 69, 51, 76, 66, 65, 119,
-109, 121, 109, 116, 66, 46, 66, 97, 48, 111, 63, 107, 74, 87, 110, 41,
-56, 47, 65, 120, 65, 43, 110, 50, 110, 54, 70, 97, 110, 56, 48, 106,
-79, 58, 110, 62, 73, 116, 77, 57, 110, 63, 110, 64, 69, 34, 70, 83,
-63, 108, 63, 93, 61, 55, 57, 115, 110, 78, 66, 105, 72, 48, 110, 79,
-110, 81, 110, 85, 72, 80, 110, 90, 110, 94, 75, 85, 110, 96, 110, 99,
-70, 95, 110, 98, 111, 79, 78, 107, 110, 111, 110, 107, 110, 105, 72, 45,
-57, 91, 75, 72, 65, 45, 110, 117, 65, 44, 110, 121, 110, 119, 61, 123,
-73, 70, 57, 93, 59, 44, 63, 109, 111, 35, 54, 83, 79, 63, 110, 125,
-68, 87, 111, 41, 55, 45, 111, 42, 51, 121, 58, 63, 51, 59, 111, 49,
-111, 55, 111, 57, 111, 56, 111, 52, 111, 63, 111, 65, 111, 60, 111, 67,
-111, 68, 111, 71, 52, 85, 111, 74, 111, 78, 111, 81, 111, 88, 68, 57,
-111, 89, 49, 60, 111, 95, 51, 85, 111, 99, 111, 102, 111, 106, 111, 107,
-70, 46, 111, 115, 73, 108, 111, 117, 75, 73, 48, 36, 111, 123, 74, 69,
-52, 89, 49, 34, 56, 49, 54, 121, 63, 111, 55, 100, 78, 89, 112, 46,
-64, 73, 50, 109, 59, 40, 63, 119, 49, 43, 49, 64, 60, 123, 78, 110,
-112, 67, 112, 69, 112, 71, 112, 73, 112, 77, 64, 68, 112, 80, 112, 83,
-112, 87, 112, 90, 112, 93, 112, 96, 112, 97, 112, 99, 112, 101, 112, 103,
-52, 90, 112, 108, 49, 36, 57, 96, 112, 114, 55, 91, 112, 117, 49, 80,
-112, 121, 52, 105, 78, 96, 112, 124, 73, 119, 113, 39, 113, 41, 72, 116,
-113, 43, 48, 59, 62, 126, 113, 46, 50, 110, 113, 51, 52, 91, 113, 57,
-113, 60, 113, 67, 60, 115, 113, 70, 67, 90, 71, 125, 67, 115, 113, 75,
-113, 79, 113, 84, 113, 87, 113, 86, 113, 89, 66, 77, 113, 91, 113, 93,
-113, 98, 113, 100, 113, 102, 57, 124, 51, 60, 63, 113, 113, 112, 113, 116,
-72, 49, 113, 124, 114, 34, 114, 35, 114, 38, 114, 45, 100, 120, 76, 37,
-114, 50, 53, 123, 79, 37, 114, 57, 48, 62, 114, 61, 75, 110, 114, 64,
-114, 65, 114, 66, 114, 75, 114, 76, 114, 80, 114, 90, 79, 76, 114, 92,
-114, 93, 48, 115, 51, 111, 114, 99, 75, 112, 114, 102, 114, 104, 68, 59,
-114, 108, 114, 112, 50, 42, 49, 117, 114, 115, 57, 99, 114, 125, 115, 37,
-49, 45, 75, 50, 115, 44, 115, 41, 115, 45, 115, 46, 114, 116, 115, 53,
-115, 49, 115, 55, 115, 57, 115, 60, 79, 73, 115, 63, 115, 64, 115, 67,
-60, 47, 115, 72, 115, 75, 78, 91, 115, 79, 115, 80, 50, 43, 115, 85,
-96, 84, 115, 93, 115, 95, 115, 99, 115, 103, 56, 93, 65, 77, 115, 108,
-73, 33, 115, 110, 115, 112, 115, 114, 115, 120, 115, 123, 78, 54, 115, 125,
-33, 42, 33, 92, 35, 53, 33, 41, 35, 73, 35, 83, 33, 79, 35, 103,
-35, 113, 33, 80, 27, 40, 73, 37, 47, 57, 67, 77, 87, 27, 36, 66,
-33, 49
- });
-
- super.setUp();
- }
-
- @Override
- public void test_CodecDynamic() throws CharacterCodingException {
- super.test_CodecDynamic();
- }
-
- @Override
- public void test_Decode() throws CharacterCodingException {
- super.test_Decode();
- }
-
- @Override
- public void test_Encode() throws CharacterCodingException {
- super.test_Encode();
- }
-
+ @Override protected void setUp() throws Exception {
+ charsetName = "ISO-2022-JP";
+ testChars = "東京 とうきょう トウキョウ Tokyo 123".toCharArray();
+ testBytes = theseBytes(0x1b, 0x24, 0x42, 0x45, 0x6c, 0x35, 0x7e, 0x1b,
+ 0x28, 0x42, 0x20, 0x1b, 0x24, 0x42, 0x24, 0x48,
+ 0x24, 0x26, 0x24, 0x2d, 0x24, 0x67, 0x24, 0x26,
+ 0x1b, 0x28, 0x42, 0x20, 0x1b, 0x24, 0x42, 0x25,
+ 0x48, 0x25, 0x26, 0x25, 0x2d, 0x25, 0x67, 0x25,
+ 0x26, 0x1b, 0x28, 0x42, 0x20, 0x54, 0x6f, 0x6b,
+ 0x79, 0x6f, 0x20, 0x31, 0x32, 0x33);
+ super.setUp();
+ }
}
diff --git a/luni/src/test/java/libcore/java/security/SecureRandomTest.java b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
index 8199120..f9edbaa 100644
--- a/luni/src/test/java/libcore/java/security/SecureRandomTest.java
+++ b/luni/src/test/java/libcore/java/security/SecureRandomTest.java
@@ -16,8 +16,6 @@
package libcore.java.security;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
-
import java.security.Provider;
import java.security.SecureRandom;
import java.security.Security;
@@ -27,7 +25,7 @@
import junit.framework.TestCase;
public class SecureRandomTest extends TestCase {
- private static final Class<? extends Provider> EXPECTED_PROVIDER = OpenSSLProvider.class;
+ private static final String EXPECTED_PROVIDER = "com.android.org.conscrypt.OpenSSLProvider";
private static final byte[] STATIC_SEED_BYTES = new byte[] {
0x0A, (byte) 0xA0, 0x01, 0x10, (byte) 0xFF, (byte) 0xF0, 0x0F
@@ -99,16 +97,16 @@
public void testGetCommonInstances_Success() throws Exception {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
assertNotNull(sr);
- assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass());
+ assertEquals(EXPECTED_PROVIDER, sr.getProvider().getClass().getName());
}
public void testNewConstructors_Success() throws Exception {
SecureRandom sr1 = new SecureRandom();
- assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass());
+ assertEquals(EXPECTED_PROVIDER, sr1.getProvider().getClass().getName());
test_SecureRandom(sr1);
SecureRandom sr2 = new SecureRandom(STATIC_SEED_BYTES);
- assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass());
+ assertEquals(EXPECTED_PROVIDER, sr2.getProvider().getClass().getName());
test_SecureRandom(sr2);
}
}
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 4afc67d..7f8b4f4 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -16,10 +16,6 @@
package libcore.java.security;
-import org.apache.harmony.xnet.provider.jsse.NativeCryptoTest;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
-
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
@@ -31,7 +27,6 @@
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
-import java.security.interfaces.RSAPrivateKey;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
@@ -86,78 +81,6 @@
}
}
- public void test_getInstance_OpenSSL_ENGINE() throws Exception {
- final String pem_private = "-----BEGIN RSA PRIVATE KEY-----\n"
- + "MIICXAIBAAKBgQDpm4KamxulJnycEzNONGM7p0CvAaoZxJEd5Dvio5b6BROdCtRN\n"
- + "lEsB+9vtB5thkyDVC7N+IW0AjtyDE6h2QP+AWa+c4dh0RM2uNVXkUWPrA8C++GHv\n"
- + "EDlxZzRGiQEMuippYfIyBVkO+4+GRvnkG4dKjzxrQYPqKUK3C4PgFW2FewIDAQAB\n"
- + "AoGAGUTSBsk6X03fcr588TundD9uNr/2V1002Ufj1msdnKPJ8FXIiy+8QVWt/2Cw\n"
- + "RQi2J3VhkAYrlUDex2rr8Qas3E9uuwKgg/MZ4EsJbnKKgkd7uBZfmZ2ogcNJ82u7\n"
- + "teVijFpdsVLDa9aczEppt5sZzyTaBrovrRb+AIRDpMw3I0ECQQD3JkWeQUA9Is1V\n"
- + "z0X/ly/kaQKQLlrwYNdiKF0qOpyTLAguI7asAS72Zj7fThk5bHLM+mmgYwkicIIb\n"
- + "67J32GQbAkEA8fkXqEnwMFYSkRmT9M/qUkwWUsMW12/AoZFI5gwKNDHZYxytGGLw\n"
- + "mC//0qKnyeUG00vz06vLApe4/Sq4ODe6IQJBALEGastF9ZtUuDsEciD2y8kRJlLb\n"
- + "wSt4Ug3u13yN6uTHnzxdPFTLrDW1WsdcC1lEQp5rpwjIpxxR9f/FvVl2V40CQHOY\n"
- + "F6EhkUjGFaCTo4b0PHCMQK3Q3PyWOmP0z+p2HfnJRpx+eoKH4YASjhfF9HoSmywd\n"
- + "wKGCFD1s1ca7vb29gYECQH86GmYZsDoLNWurEVJbkmCr7X1+xwim6umdrNKR27P7\n"
- + "F1y0Sa3YY+LiiRb+IRSWE/onlP+28LIzWGF4lcTfDMc=\n"
- + "-----END RSA PRIVATE KEY-----";
-
- final byte[] der_public = new byte[] {
- (byte) 0x30, (byte) 0x81, (byte) 0x9F, (byte) 0x30, (byte) 0x0D, (byte) 0x06,
- (byte) 0x09, (byte) 0x2A, (byte) 0x86, (byte) 0x48, (byte) 0x86, (byte) 0xF7,
- (byte) 0x0D, (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x05, (byte) 0x00,
- (byte) 0x03, (byte) 0x81, (byte) 0x8D, (byte) 0x00, (byte) 0x30, (byte) 0x81,
- (byte) 0x89, (byte) 0x02, (byte) 0x81, (byte) 0x81, (byte) 0x00, (byte) 0xE9,
- (byte) 0x9B, (byte) 0x82, (byte) 0x9A, (byte) 0x9B, (byte) 0x1B, (byte) 0xA5,
- (byte) 0x26, (byte) 0x7C, (byte) 0x9C, (byte) 0x13, (byte) 0x33, (byte) 0x4E,
- (byte) 0x34, (byte) 0x63, (byte) 0x3B, (byte) 0xA7, (byte) 0x40, (byte) 0xAF,
- (byte) 0x01, (byte) 0xAA, (byte) 0x19, (byte) 0xC4, (byte) 0x91, (byte) 0x1D,
- (byte) 0xE4, (byte) 0x3B, (byte) 0xE2, (byte) 0xA3, (byte) 0x96, (byte) 0xFA,
- (byte) 0x05, (byte) 0x13, (byte) 0x9D, (byte) 0x0A, (byte) 0xD4, (byte) 0x4D,
- (byte) 0x94, (byte) 0x4B, (byte) 0x01, (byte) 0xFB, (byte) 0xDB, (byte) 0xED,
- (byte) 0x07, (byte) 0x9B, (byte) 0x61, (byte) 0x93, (byte) 0x20, (byte) 0xD5,
- (byte) 0x0B, (byte) 0xB3, (byte) 0x7E, (byte) 0x21, (byte) 0x6D, (byte) 0x00,
- (byte) 0x8E, (byte) 0xDC, (byte) 0x83, (byte) 0x13, (byte) 0xA8, (byte) 0x76,
- (byte) 0x40, (byte) 0xFF, (byte) 0x80, (byte) 0x59, (byte) 0xAF, (byte) 0x9C,
- (byte) 0xE1, (byte) 0xD8, (byte) 0x74, (byte) 0x44, (byte) 0xCD, (byte) 0xAE,
- (byte) 0x35, (byte) 0x55, (byte) 0xE4, (byte) 0x51, (byte) 0x63, (byte) 0xEB,
- (byte) 0x03, (byte) 0xC0, (byte) 0xBE, (byte) 0xF8, (byte) 0x61, (byte) 0xEF,
- (byte) 0x10, (byte) 0x39, (byte) 0x71, (byte) 0x67, (byte) 0x34, (byte) 0x46,
- (byte) 0x89, (byte) 0x01, (byte) 0x0C, (byte) 0xBA, (byte) 0x2A, (byte) 0x69,
- (byte) 0x61, (byte) 0xF2, (byte) 0x32, (byte) 0x05, (byte) 0x59, (byte) 0x0E,
- (byte) 0xFB, (byte) 0x8F, (byte) 0x86, (byte) 0x46, (byte) 0xF9, (byte) 0xE4,
- (byte) 0x1B, (byte) 0x87, (byte) 0x4A, (byte) 0x8F, (byte) 0x3C, (byte) 0x6B,
- (byte) 0x41, (byte) 0x83, (byte) 0xEA, (byte) 0x29, (byte) 0x42, (byte) 0xB7,
- (byte) 0x0B, (byte) 0x83, (byte) 0xE0, (byte) 0x15, (byte) 0x6D, (byte) 0x85,
- (byte) 0x7B, (byte) 0x02, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x01
- };
-
- // We only need to test this on the OpenSSL provider.
- Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
-
- /* ENGINE-based private key */
- NativeCryptoTest.loadTestEngine();
- OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
- PrivateKey privKey = engine.getPrivateKeyById(pem_private);
- assertTrue(privKey instanceof RSAPrivateKey);
-
- /* Non-ENGINE-based public key */
- KeyFactory kf = KeyFactory.getInstance("RSA", p);
- PublicKey pubKey = kf.generatePublic(new X509EncodedKeySpec(der_public));
-
- KeyPair kp = new KeyPair(pubKey, privKey);
-
- Set<Provider.Service> services = p.getServices();
- for (Provider.Service service : services) {
- if ("Signature".equals(service.getType()) && service.getAlgorithm().contains("RSA")) {
- Signature sig1 = Signature.getInstance(service.getAlgorithm(), p);
- test_Signature(sig1, kp);
- }
- }
-
- }
-
private final Map<String, KeyPair> keypairAlgorithmToInstance
= new HashMap<String, KeyPair>();
diff --git a/luni/src/test/java/libcore/java/text/CollatorTest.java b/luni/src/test/java/libcore/java/text/CollatorTest.java
index 0c718c8..0a61f04 100644
--- a/luni/src/test/java/libcore/java/text/CollatorTest.java
+++ b/luni/src/test/java/libcore/java/text/CollatorTest.java
@@ -134,15 +134,19 @@
assertCollationElementIterator(coll.getCollationElementIterator(it), offsets);
}
- public void testGetCollationElementIteratorString() throws Exception {
- assertGetCollationElementIteratorString(new Locale("es", "", "TRADITIONAL"), "cha", 0, 2, 3);
+ public void testGetCollationElementIteratorString_es() throws Exception {
assertGetCollationElementIteratorString(new Locale("es", "", ""), "cha", 0, 1, 2, 3);
+ }
+
+ public void testGetCollationElementIteratorString_de_DE() throws Exception {
assertGetCollationElementIteratorString(new Locale("de", "DE", ""), "\u00e6b", 0, 1, 1, 1, 1, 2);
}
- public void testGetCollationElementIteratorCharacterIterator() throws Exception {
- assertGetCollationElementIteratorCharacterIterator(new Locale("es", "", "TRADITIONAL"), "cha", 0, 2, 3);
+ public void testGetCollationElementIteratorCharacterIterator_es() throws Exception {
assertGetCollationElementIteratorCharacterIterator(new Locale("es", "", ""), "cha", 0, 1, 2, 3);
+ }
+
+ public void testGetCollationElementIteratorCharacterIterator_de_DE() throws Exception {
assertGetCollationElementIteratorCharacterIterator(new Locale("de", "DE", ""), "\u00e6b", 0, 1, 1, 1, 1, 2);
}
}
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index a2f93a8..1e40f8a 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -22,8 +22,8 @@
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
+import java.util.Currency;
import java.util.Locale;
-import tests.support.Support_Locale;
public class DecimalFormatTest extends junit.framework.TestCase {
public void test_exponentSeparator() throws Exception {
@@ -80,11 +80,9 @@
assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
Locale.US, "9,990,000,000,000,000,000,000,000,000,000,000");
- Locale inLocale = new Locale("en", "IN");
- if (Support_Locale.isLocaleAvailable(inLocale)) {
- assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
- inLocale, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000");
- }
+ Locale en_IN = new Locale("en", "IN");
+ assertDecFmtWithMultiplierAndFractionByLocale("3330000000000000000000000000000000", 3, 4,
+ en_IN, "9,99,00,00,00,00,00,00,00,00,00,00,00,00,00,00,000");
}
public void testBigDecimalTestBigIntWithMultiplier() {
@@ -103,22 +101,20 @@
assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
Locale.US, "-987,654,321,098,765,432,109,876,543,210");
- Locale inLocale = new Locale("en", "IN");
- if (Support_Locale.isLocaleAvailable(inLocale)) {
- assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
- inLocale, "1,23,45,67,89,01,23,450");
- assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
- inLocale, "12,34,56,78,90,12,34,56,78,900");
- assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
- inLocale, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
+ Locale en_IN = new Locale("en", "IN");
+ assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", 10, 0,
+ en_IN, "1,23,45,67,89,01,23,450");
+ assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", 10, 0,
+ en_IN, "12,34,56,78,90,12,34,56,78,900");
+ assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", 10, 0,
+ en_IN, "9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
- assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
- inLocale, "-1,23,45,67,89,01,23,450");
- assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
- inLocale, "-12,34,56,78,90,12,34,56,78,900");
- assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
- inLocale, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
- }
+ assertDecFmtWithMultiplierAndFractionByLocale("123456789012345", -10, 0,
+ en_IN, "-1,23,45,67,89,01,23,450");
+ assertDecFmtWithMultiplierAndFractionByLocale("12345678901234567890", -10, 0,
+ en_IN, "-12,34,56,78,90,12,34,56,78,900");
+ assertDecFmtWithMultiplierAndFractionByLocale("98765432109876543210987654321", -10, 0,
+ en_IN, "-9,87,65,43,21,09,87,65,43,21,09,87,65,43,210");
}
public void testBigDecimalICUConsistency() {
@@ -176,4 +172,29 @@
BigDecimal d = new BigDecimal(value);
assertEquals(expectedResult, df.format(d));
}
+
+ public void testSetZeroDigitForPattern() {
+ DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
+ decimalFormatSymbols.setZeroDigit('a');
+ DecimalFormat formatter = new DecimalFormat();
+ formatter.setDecimalFormatSymbols(decimalFormatSymbols);
+ formatter.applyLocalizedPattern("#.aa");
+ assertEquals("e.fa", formatter.format(4.50));
+ }
+
+ public void testSetZeroDigitForFormatting() {
+ DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols();
+ decimalFormatSymbols.setZeroDigit('a');
+ DecimalFormat formatter = new DecimalFormat();
+ formatter.setDecimalFormatSymbols(decimalFormatSymbols);
+ formatter.applyLocalizedPattern("#");
+ assertEquals("eadacab", formatter.format(4030201));
+ }
+
+ public void testBug9087737() throws Exception {
+ DecimalFormat df = (DecimalFormat) NumberFormat.getCurrencyInstance(Locale.US);
+ // These shouldn't make valgrind unhappy.
+ df.setCurrency(Currency.getInstance("CHF"));
+ df.setCurrency(Currency.getInstance("GBP"));
+ }
}
diff --git a/luni/src/test/java/libcore/java/text/NumberFormatTest.java b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
index ce80bd1..1a14462 100644
--- a/luni/src/test/java/libcore/java/text/NumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/NumberFormatTest.java
@@ -23,7 +23,6 @@
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.util.Locale;
-import tests.support.Support_Locale;
public class NumberFormatTest extends junit.framework.TestCase {
// NumberFormat.format(Object, StringBuffer, FieldPosition) guarantees it calls doubleValue for
@@ -66,9 +65,6 @@
}
public void test_getIntegerInstance_ar() throws Exception {
- if (!Support_Locale.isLocaleAvailable(new Locale("ar"))) {
- return;
- }
NumberFormat numberFormat = NumberFormat.getNumberInstance(new Locale("ar"));
assertEquals("#0.###;#0.###-", ((DecimalFormat) numberFormat).toPattern());
NumberFormat integerFormat = NumberFormat.getIntegerInstance(new Locale("ar"));
@@ -77,9 +73,6 @@
public void test_numberLocalization() throws Exception {
Locale arabic = new Locale("ar");
- if (!Support_Locale.isLocaleAvailable(arabic)) {
- return;
- }
NumberFormat nf = NumberFormat.getNumberInstance(arabic);
assertEquals('\u0660', new DecimalFormatSymbols(arabic).getZeroDigit());
assertEquals("١٢٣٤٥٦٧٨٩٠", nf.format(1234567890));
diff --git a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
index 7bb5545..b7ae098 100644
--- a/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/OldNumberFormatTest.java
@@ -26,7 +26,6 @@
import java.util.Currency;
import java.util.Locale;
import junit.framework.TestCase;
-import tests.support.Support_Locale;
public class OldNumberFormatTest extends TestCase {
@@ -41,25 +40,22 @@
// try with a locale that has a different integer pattern
Locale chLocale = new Locale("de", "CH");
- if (Support_Locale.isLocaleAvailable(chLocale)) {
- format = (DecimalFormat) NumberFormat.getIntegerInstance(chLocale);
- assertEquals("#,##0", format.toPattern());
- assertEquals("-36", format.format(-35.76));
- assertEquals(new Long(-36), format.parse("-36"));
- assertEquals(new Long(-36), format.parseObject("-36"));
- assertEquals(0, format.getMaximumFractionDigits());
- assertTrue(format.isParseIntegerOnly());
- }
+ format = (DecimalFormat) NumberFormat.getIntegerInstance(chLocale);
+ assertEquals("#,##0", format.toPattern());
+ assertEquals("-36", format.format(-35.76));
+ assertEquals(new Long(-36), format.parse("-36"));
+ assertEquals(new Long(-36), format.parseObject("-36"));
+ assertEquals(0, format.getMaximumFractionDigits());
+ assertTrue(format.isParseIntegerOnly());
+
Locale arLocale = new Locale("ar", "AE");
- if (Support_Locale.isLocaleAvailable(arLocale)) {
- format = (DecimalFormat) NumberFormat.getIntegerInstance(arLocale);
- assertEquals("#0;#0-", format.toPattern());
- assertEquals("\u0666-", format.format(-6));
- assertEquals(new Long(-36), format.parse("36-"));
- assertEquals(new Long(-36), format.parseObject("36-"));
- assertEquals(0, format.getMaximumFractionDigits());
- assertTrue(format.isParseIntegerOnly());
- }
+ format = (DecimalFormat) NumberFormat.getIntegerInstance(arLocale);
+ assertEquals("#0;#0-", format.toPattern());
+ assertEquals("\u0666-", format.format(-6));
+ assertEquals(new Long(-36), format.parse("36-"));
+ assertEquals(new Long(-36), format.parseObject("36-"));
+ assertEquals(0, format.getMaximumFractionDigits());
+ assertTrue(format.isParseIntegerOnly());
}
public void test_setMaximumIntegerDigits() {
@@ -114,15 +110,11 @@
parseObjectTest(NumberFormat.getInstance(), "123.123abc123",
new ParsePosition(3), new Double(0.123), 7, true);
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- parseObjectTest(NumberFormat.getInstance(Locale.FRANCE),
- "asd123,123abc123",
- new ParsePosition(3), new Double(123.123), 10, true);
+ parseObjectTest(NumberFormat.getInstance(Locale.FRANCE), "asd123,123abc123",
+ new ParsePosition(3), new Double(123.123), 10, true);
- parseObjectTest(NumberFormat.getInstance(Locale.FRANCE),
- "test test",
- new ParsePosition(0), null, 0, false);
- }
+ parseObjectTest(NumberFormat.getInstance(Locale.FRANCE), "test test",
+ new ParsePosition(0), null, 0, false);
parseObjectTest(NumberFormat.getIntegerInstance(),
"asd123.123abc123",
@@ -222,14 +214,12 @@
out.toString());
Locale deLocale = new Locale("de", "CH");
- if (Support_Locale.isLocaleAvailable(deLocale)) {
- NumberFormat nf2 = NumberFormat.getInstance(deLocale);
- out = nf2.format(-1234567890.0123456789);
- // use de_CH instead
- // assertEquals("Wrong result for double : " + out, "1,234,567,890.012-",
- // out.toString());
- assertEquals("Wrong result for double : " + out, "-1'234'567'890.012", out.toString());
- }
+ NumberFormat nf2 = NumberFormat.getInstance(deLocale);
+ out = nf2.format(-1234567890.0123456789);
+ // use de_CH instead
+ // assertEquals("Wrong result for double : " + out, "1,234,567,890.012-",
+ // out.toString());
+ assertEquals("Wrong result for double : " + out, "-1'234'567'890.012", out.toString());
out = nf1.format(1.0001);
assertEquals("Wrong result for for double: " + out, "1", out.toString());
@@ -251,14 +241,12 @@
"-9,223,372,036,854,775,808", out.toString());
Locale deLocale = new Locale("de", "CH");
- if (Support_Locale.isLocaleAvailable(deLocale)) {
- NumberFormat nf2 = NumberFormat.getInstance(deLocale);
- out = nf2.format(-1234567890);
- // use de_CH instead
- // assertEquals("Wrong result for double : " + out, "-1 234 567 890", out
- // .toString());
- assertEquals("Wrong result for double : " + out, "-1'234'567'890", out.toString());
- }
+ NumberFormat nf2 = NumberFormat.getInstance(deLocale);
+ out = nf2.format(-1234567890);
+ // use de_CH instead
+ // assertEquals("Wrong result for double : " + out, "-1 234 567 890", out
+ // .toString());
+ assertEquals("Wrong result for double : " + out, "-1'234'567'890", out.toString());
// the Locale data of icu uses \uc2a0
out = nf1.format(1);
@@ -322,18 +310,16 @@
assertEquals("$1.00", format.format(0.999));
Locale atLocale = new Locale("de", "AT");
- if (Support_Locale.isLocaleAvailable(atLocale)) {
- format = NumberFormat.getCurrencyInstance(atLocale);
- // BEGIN android-changed: ICU uses non-breaking space after the euro sign; the RI uses ' '.
- assertEquals("\u20ac\u00a035,76", format.format(35.76));
- assertEquals("\u20ac\u00a0123.456,79", format.format(123456.789));
- assertEquals("\u20ac\u00a00,10", format.format(0.1));
- assertEquals("\u20ac\u00a01,00", format.format(0.999));
- try {
- NumberFormat.getCurrencyInstance(null);
- fail("java.lang.NullPointerException is not thrown");
- } catch (java.lang.NullPointerException expected) {
- }
+ format = NumberFormat.getCurrencyInstance(atLocale);
+ // BEGIN android-changed: ICU uses non-breaking space after the euro sign; the RI uses ' '.
+ assertEquals("\u20ac\u00a035,76", format.format(35.76));
+ assertEquals("\u20ac\u00a0123.456,79", format.format(123456.789));
+ assertEquals("\u20ac\u00a00,10", format.format(0.1));
+ assertEquals("\u20ac\u00a01,00", format.format(0.999));
+ try {
+ NumberFormat.getCurrencyInstance(null);
+ fail("java.lang.NullPointerException is not thrown");
+ } catch (java.lang.NullPointerException expected) {
}
}
@@ -357,18 +343,17 @@
}
public void test_getInstanceLjava_util_Locale() {
- Locale testLocale = new Locale("de", "CH");
+ Locale de_CH = new Locale("de", "CH");
Locale.setDefault(Locale.US);
- if (Support_Locale.isLocaleAvailable(testLocale)) {
- NumberFormat format = NumberFormat.getInstance(testLocale);
+ NumberFormat format = NumberFormat.getInstance(de_CH);
- assertNotSame(null, format);
- assertTrue(format instanceof NumberFormat);
+ assertNotSame(null, format);
+ assertTrue(format instanceof NumberFormat);
- assertEquals("1'234'567'890.099", format.format(1234567890.0987654321));
- assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
- assertEquals("123'456'789", format.format(123456789));
- }
+ assertEquals("1'234'567'890.099", format.format(1234567890.0987654321));
+ assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
+ assertEquals("123'456'789", format.format(123456789));
+
try {
NumberFormat.getInstance(null);
fail("java.lang.NullPointerException is not thrown");
@@ -398,15 +383,14 @@
public void test_getNumberInstanceLjava_util_Locale() {
Locale.setDefault(Locale.US);
Locale deLocale = new Locale("de", "CH");
- if (Support_Locale.isLocaleAvailable(deLocale)) {
- NumberFormat format = NumberFormat.getNumberInstance(deLocale);
- assertNotSame("Instance is null", null, format);
- assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
+ NumberFormat format = NumberFormat.getNumberInstance(deLocale);
+ assertNotSame("Instance is null", null, format);
+ assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
- assertEquals("-1'234'567'890.099", format.format(-1234567890.0987654321));
- assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
- assertEquals("123'456'789", format.format(123456789));
- }
+ assertEquals("-1'234'567'890.099", format.format(-1234567890.0987654321));
+ assertEquals("#,##0.###", ((DecimalFormat) format).toPattern());
+ assertEquals("123'456'789", format.format(123456789));
+
try {
NumberFormat.getInstance(null);
fail("java.lang.NullPointerException is not thrown");
@@ -436,16 +420,15 @@
public void test_getPercentInstanceLjava_util_Locale() {
Locale csLocale = new Locale("cs", "CZ");
Locale.setDefault(Locale.US);
- if (Support_Locale.isLocaleAvailable(csLocale)) {
- NumberFormat format = NumberFormat.getPercentInstance(csLocale);
- assertNotSame("Instance is null", null, format);
- assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
+ NumberFormat format = NumberFormat.getPercentInstance(csLocale);
+ assertNotSame("Instance is null", null, format);
+ assertTrue("Object is not instance of NumberFormat", format instanceof NumberFormat);
- assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", format.format(1234567890.0987654321));
- assertEquals("#,##0\u00a0%", ((DecimalFormat) format).toPattern());
- assertEquals("12\u00a0345\u00a0678\u00a0900\u00a0%", format.format(123456789));
- }
+ assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", format.format(1234567890.0987654321));
+ assertEquals("#,##0\u00a0%", ((DecimalFormat) format).toPattern());
+ assertEquals("12\u00a0345\u00a0678\u00a0900\u00a0%", format.format(123456789));
+
try {
NumberFormat.getInstance(null);
fail("java.lang.NullPointerException is not thrown");
@@ -602,25 +585,23 @@
"-1,234,567,890.1", nf1.format(-1234567890.1));
Locale csLocale = new Locale("cs", "CZ");
- if (Support_Locale.isLocaleAvailable(csLocale)) {
- NumberFormat nf2 = NumberFormat.getPercentInstance(csLocale);
- nf2.setGroupingUsed(false);
+ NumberFormat nf2 = NumberFormat.getPercentInstance(csLocale);
+ nf2.setGroupingUsed(false);
- assertEquals("123456789010\u00a0%", nf2.format(1234567890.1));
+ assertEquals("123456789010\u00a0%", nf2.format(1234567890.1));
- assertEquals("-123456789010\u00a0%", nf2.format(-1234567890.1));
- assertEquals("1,234,567,890.1", nf1.format(1234567890.1));
+ assertEquals("-123456789010\u00a0%", nf2.format(-1234567890.1));
+ assertEquals("1,234,567,890.1", nf1.format(1234567890.1));
- nf2.setGroupingUsed(true);
- assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
+ nf2.setGroupingUsed(true);
+ assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
- assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
+ assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
- nf2.setGroupingUsed(true);
- assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
+ nf2.setGroupingUsed(true);
+ assertEquals("123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(1234567890.1));
- assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
- }
+ assertEquals("-123\u00a0456\u00a0789\u00a0010\u00a0%", nf2.format(-1234567890.1));
}
public void test_isParseIntegerOnly() {
diff --git a/luni/src/test/java/libcore/java/util/FormatterTest.java b/luni/src/test/java/libcore/java/util/FormatterTest.java
index 596e946..043c06b 100644
--- a/luni/src/test/java/libcore/java/util/FormatterTest.java
+++ b/luni/src/test/java/libcore/java/util/FormatterTest.java
@@ -18,16 +18,14 @@
import java.math.BigDecimal;
import java.util.Calendar;
+import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
-import tests.support.Support_Locale;
public class FormatterTest extends junit.framework.TestCase {
public void test_numberLocalization() throws Exception {
Locale arabic = new Locale("ar");
- if (!Support_Locale.isLocaleAvailable(arabic)) {
- return;
- }
+
// Check the fast path for %d:
assertEquals("12 \u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669\u0660 34",
String.format(arabic, "12 %d 34", 1234567890));
@@ -135,4 +133,42 @@
public void test42936() throws Exception {
assertEquals("0.00000000000000", String.format("%.15g",0.0d));
}
+
+ // https://code.google.com/p/android/issues/detail?id=53983
+ public void test53983() throws Exception {
+ checkFormat("00", "H", 00);
+ checkFormat( "0", "k", 00);
+ checkFormat("12", "I", 00);
+ checkFormat("12", "l", 00);
+
+ checkFormat("01", "H", 01);
+ checkFormat( "1", "k", 01);
+ checkFormat("01", "I", 01);
+ checkFormat( "1", "l", 01);
+
+ checkFormat("12", "H", 12);
+ checkFormat("12", "k", 12);
+ checkFormat("12", "I", 12);
+ checkFormat("12", "l", 12);
+
+ checkFormat("13", "H", 13);
+ checkFormat("13", "k", 13);
+ checkFormat("01", "I", 13);
+ checkFormat( "1", "l", 13);
+
+ checkFormat("00", "H", 24);
+ checkFormat( "0", "k", 24);
+ checkFormat("12", "I", 24);
+ checkFormat("12", "l", 24);
+ }
+
+ private static void checkFormat(String expected, String pattern, int hour) {
+ TimeZone utc = TimeZone.getTimeZone("UTC");
+
+ Calendar c = new GregorianCalendar(utc);
+ c.set(2013, Calendar.JANUARY, 1, hour, 00);
+
+ assertEquals(expected, String.format(Locale.US, "%t" + pattern, c));
+ assertEquals(expected, String.format(Locale.US, "%T" + pattern, c));
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/ObjectsTest.java b/luni/src/test/java/libcore/java/util/ObjectsTest.java
new file mode 100644
index 0000000..93be541
--- /dev/null
+++ b/luni/src/test/java/libcore/java/util/ObjectsTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+public class ObjectsTest extends junit.framework.TestCase {
+ public static final class Hello {
+ public String toString() { return "hello"; }
+ }
+
+ public void test_compare() throws Exception {
+ assertEquals(0, Objects.compare(null, null, String.CASE_INSENSITIVE_ORDER));
+ assertEquals(0, Objects.compare("a", "A", String.CASE_INSENSITIVE_ORDER));
+ assertEquals(-1, Objects.compare("a", "b", String.CASE_INSENSITIVE_ORDER));
+ assertEquals(1, Objects.compare("b", "a", String.CASE_INSENSITIVE_ORDER));
+ }
+
+ public void test_deepEquals() throws Exception {
+ int[] xs = new int[3];
+ int[] ys = new int[4];
+ int[] zs = new int[3];
+ String[] o1 = new String[] { "hello" };
+ String[] o2 = new String[] { "world" };
+ String[] o3 = new String[] { "hello" };
+ assertTrue(Objects.deepEquals(null, null));
+ assertFalse(Objects.deepEquals(xs, null));
+ assertFalse(Objects.deepEquals(null, xs));
+ assertTrue(Objects.deepEquals(xs, xs));
+ assertTrue(Objects.deepEquals(xs, zs));
+ assertFalse(Objects.deepEquals(xs, ys));
+ assertTrue(Objects.deepEquals(o1, o1));
+ assertTrue(Objects.deepEquals(o1, o3));
+ assertFalse(Objects.deepEquals(o1, o2));
+ assertTrue(Objects.deepEquals("hello", "hello"));
+ assertFalse(Objects.deepEquals("hello", "world"));
+ }
+
+ public void test_equals() throws Exception {
+ Hello h1 = new Hello();
+ Hello h2 = new Hello();
+ assertTrue(Objects.equals(null, null));
+ assertFalse(Objects.equals(h1, null));
+ assertFalse(Objects.equals(null, h1));
+ assertFalse(Objects.equals(h1, h2));
+ assertTrue(Objects.equals(h1, h1));
+ }
+
+ public void test_hash() throws Exception {
+ assertEquals(Arrays.hashCode(new Object[0]), Objects.hash());
+ assertEquals(31, Objects.hash((Object) null));
+ assertEquals(0, Objects.hash((Object[]) null));
+ assertEquals(-1107615551, Objects.hash("hello", "world"));
+ assertEquals(23656287, Objects.hash("hello", "world", null));
+ }
+
+ public void test_hashCode() throws Exception {
+ Hello h = new Hello();
+ assertEquals(h.hashCode(), Objects.hashCode(h));
+ assertEquals(0, Objects.hashCode(null));
+ }
+
+ public void test_requireNonNull_T() throws Exception {
+ Hello h = new Hello();
+ assertEquals(h, Objects.requireNonNull(h));
+ try {
+ Objects.requireNonNull(null);
+ fail();
+ } catch (NullPointerException expected) {
+ assertEquals(null, expected.getMessage());
+ }
+ }
+
+ public void test_requireNonNull_T_String() throws Exception {
+ Hello h = new Hello();
+ assertEquals(h, Objects.requireNonNull(h, "test"));
+ try {
+ Objects.requireNonNull(null, "message");
+ fail();
+ } catch (NullPointerException expected) {
+ assertEquals("message", expected.getMessage());
+ }
+ try {
+ Objects.requireNonNull(null, null);
+ fail();
+ } catch (NullPointerException expected) {
+ assertEquals(null, expected.getMessage());
+ }
+ }
+
+ public void test_toString_Object() throws Exception {
+ assertEquals("hello", Objects.toString(new Hello()));
+ assertEquals("null", Objects.toString(null));
+ }
+
+ public void test_toString_Object_String() throws Exception {
+ assertEquals("hello", Objects.toString(new Hello(), "world"));
+ assertEquals("world", Objects.toString(null, "world"));
+ assertEquals(null, Objects.toString(null, null));
+ }
+}
diff --git a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
index ad9009a..4bd858c 100644
--- a/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/OldAndroidLocaleTest.java
@@ -177,10 +177,8 @@
assertFalse("Charset KLINGON must not be supported",
Charset.isSupported("KLINGON"));
- // Make sure our local change to the real translation table used for
- // EUC-JP doesn't get lost.
- Charset cs = Charset.forName("EUC-JP");
- assertTrue("EUC-JP must use 'ibm-954_P101-2007'", cs.aliases().contains("ibm-954_P101-2007"));
+ // 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/OldFormatterTest.java b/luni/src/test/java/libcore/java/util/OldFormatterTest.java
index 53d8eb2..3b4788b 100644
--- a/luni/src/test/java/libcore/java/util/OldFormatterTest.java
+++ b/luni/src/test/java/libcore/java/util/OldFormatterTest.java
@@ -24,7 +24,6 @@
import java.util.IllegalFormatFlagsException;
import java.util.Locale;
import junit.framework.TestCase;
-import tests.support.Support_Locale;
public final class OldFormatterTest extends TestCase {
@@ -59,21 +58,17 @@
Formatter fNoL = null;
cal.set(2008, Calendar.SEPTEMBER, 23, 18, 30);
- if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
- fLoc = new Formatter(Locale.GERMAN);
- fNoL = new Formatter(Locale.GERMAN);
- fLoc.format(Locale.US, "%f", val);
- fNoL.format("%f", val);
- assertFalse(fLoc.toString().equals(fNoL.toString()));
- }
+ fLoc = new Formatter(Locale.GERMAN);
+ fNoL = new Formatter(Locale.GERMAN);
+ fLoc.format(Locale.US, "%f", val);
+ fNoL.format("%f", val);
+ assertFalse(fLoc.toString().equals(fNoL.toString()));
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- fLoc = new Formatter(Locale.FRANCE);
- fNoL = new Formatter(Locale.FRANCE);
- fLoc.format(Locale.US, "%f", val);
- fNoL.format("%f", val);
- assertFalse(fLoc.toString().equals(fNoL.toString()));
- }
+ fLoc = new Formatter(Locale.FRANCE);
+ fNoL = new Formatter(Locale.FRANCE);
+ fLoc.format(Locale.US, "%f", val);
+ fNoL.format("%f", val);
+ assertFalse(fLoc.toString().equals(fNoL.toString()));
fLoc = new Formatter(Locale.US);
fNoL = new Formatter(Locale.US);
@@ -81,21 +76,17 @@
fNoL.format("%f", val);
assertTrue(fLoc.toString().equals(fNoL.toString()));
- if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
- fLoc = new Formatter(Locale.GERMAN);
- fNoL = new Formatter(Locale.GERMAN);
- fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal, cal, cal);
- fNoL.format("%tA %tB %td %tT", cal, cal, cal, cal);
- assertFalse(fLoc.toString().equals(fNoL.toString()));
- }
+ fLoc = new Formatter(Locale.GERMAN);
+ fNoL = new Formatter(Locale.GERMAN);
+ fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal, cal, cal);
+ fNoL.format("%tA %tB %td %tT", cal, cal, cal, cal);
+ assertFalse(fLoc.toString().equals(fNoL.toString()));
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- fLoc = new Formatter(Locale.FRANCE);
- fNoL = new Formatter(Locale.FRANCE);
- fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal, cal, cal);
- fNoL.format("%tA %tB %td %tT", cal, cal, cal, cal);
- assertFalse(fLoc.toString().equals(fNoL.toString()));
- }
+ fLoc = new Formatter(Locale.FRANCE);
+ fNoL = new Formatter(Locale.FRANCE);
+ fLoc.format(Locale.US, "%tA %tB %td %tT", cal, cal, cal, cal);
+ fNoL.format("%tA %tB %td %tT", cal, cal, cal, cal);
+ assertFalse(fLoc.toString().equals(fNoL.toString()));
fLoc = new Formatter(Locale.US);
fNoL = new Formatter(Locale.US);
@@ -107,31 +98,25 @@
"%+ a", "%+ A", "%-03e", "%-03E", "%-03g", "%-03G", "%-03f",
"%-03a", "%-03A" };
for (int i = 0; i < illFlags.length; i++) {
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- try {
- fLoc = new Formatter(Locale.US);
- fLoc.format(Locale.FRANCE, illFlags[i], 1.23d);
- fail("should throw IllegalFormatFlagsException");
- } catch (IllegalFormatFlagsException expected) {
- }
+ try {
+ fLoc = new Formatter(Locale.US);
+ fLoc.format(Locale.FRANCE, illFlags[i], 1.23d);
+ fail("should throw IllegalFormatFlagsException");
+ } catch (IllegalFormatFlagsException expected) {
}
-
- if (Support_Locale.isLocaleAvailable(Locale.CANADA)) {
- try {
- fLoc = new Formatter(Locale.CANADA);
- fLoc.format(Locale.GERMAN, illFlags[i], (Double) null);
- fail("should throw IllegalFormatFlagsException");
- } catch (IllegalFormatFlagsException expected) {
- }
+ try {
+ fLoc = new Formatter(Locale.CANADA);
+ fLoc.format(Locale.GERMAN, illFlags[i], (Double) null);
+ fail("should throw IllegalFormatFlagsException");
+ } catch (IllegalFormatFlagsException expected) {
}
}
- fLoc.close();
- if (Support_Locale.isLocaleAvailable(Locale.GERMAN)) {
- try {
- fLoc.format(Locale.GERMAN, "%f", val);
- } catch (FormatterClosedException expected) {
- }
+ fLoc.close();
+ try {
+ fLoc.format(Locale.GERMAN, "%f", val);
+ fail();
+ } catch (FormatterClosedException expected) {
}
}
}
diff --git a/luni/src/test/java/libcore/java/util/OldScannerTest.java b/luni/src/test/java/libcore/java/util/OldScannerTest.java
index 9bac1f4..4f63d92 100644
--- a/luni/src/test/java/libcore/java/util/OldScannerTest.java
+++ b/luni/src/test/java/libcore/java/util/OldScannerTest.java
@@ -15,7 +15,13 @@
*/
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;
@@ -31,12 +37,10 @@
public final class OldScannerTest extends TestCase {
- private Scanner s;
-
public void test_findWithinHorizon_Ljava_lang_StringI() {
// This method searches through the input up to the specified search
// horizon(exclusive).
- s = new Scanner("123test");
+ Scanner s = new Scanner("123test");
String result = s.findWithinHorizon("\\p{Lower}", 5);
assertEquals("t", result);
MatchResult mresult = s.match();
@@ -265,30 +269,7 @@
}
public void test_findInLine_LString() {
- s = new Scanner("test");
- try {
- s.findInLine((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
- }
-
- s.close();
- try {
- s.findInLine((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // expected
- }
- try {
- s.findInLine("test");
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // exptected
- }
-
- s = new Scanner("");
-
+ Scanner s = new Scanner("");
String result = s.findInLine("^");
assertEquals("", result);
MatchResult matchResult = s.match();
@@ -325,8 +306,7 @@
try {
matchResult = s.match();
fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
+ } catch (IllegalStateException expected) {
}
assertEquals(0, matchResult.start());
assertEquals(4, matchResult.end());
@@ -392,105 +372,6 @@
result = s.findInLine("est");
}
- public void test_skip_LPattern() {
- s = new Scanner("test");
- try {
- s.skip((String) null);
- fail("Should throw NullPointerException");
- } catch (NullPointerException e) {
- // 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
- }
- // Then, no matchResult will be thrown out.
- try {
- s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
-
- s.skip(Pattern.compile("\\p{Digit}"));
- MatchResult matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(1, matchResult.end());
-
- s.skip(Pattern.compile("\\p{Digit}+"));
- matchResult = s.match();
- assertEquals(1, matchResult.start());
- assertEquals(4, matchResult.end());
-
- s.close();
- try {
- s.skip(Pattern.compile("test"));
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // 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
- }
- try {
- s.match();
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
- s.skip(Pattern.compile("\\p{Digit}{3}\\p{Lower}"));
- matchResult = s.match();
- assertEquals(0, matchResult.start());
- assertEquals(4, matchResult.end());
-
- s.close();
- try {
- s.skip((Pattern) null);
- fail("Should throw IllegalStateException");
- } catch (IllegalStateException e) {
- // expected
- }
-
- StringBuilder stringBuilder = new StringBuilder();
- char [] chars = new char[1024];
- Arrays.fill(chars, 'a');
- stringBuilder.append(chars);
- stringBuilder.append('3');
- s = new Scanner(stringBuilder.toString());
- s.skip(Pattern.compile("\\p{Lower}+\\p{Digit}"));
- 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');
- stringBuilder = new StringBuilder();
- stringBuilder.append(chars);
- s = new Scanner(stringBuilder.toString());
- s.skip(Pattern.compile(".*"));
- 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();
- assertEquals(102400, matchResult.start());
- assertEquals(102400, matchResult.end());
- }
-
public void test_Constructor_LReadableByteChannel() throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open();
ssc.socket().bind(null);
@@ -529,27 +410,33 @@
}
}
- private static class MockStringReader2Read extends StringReader {
- private int timesRead = 1;
+ // http://code.google.com/p/android/issues/detail?id=57050
+ public void testPerformance() throws Exception {
+ int count = 100000;
- public MockStringReader2Read(String param) {
- super(param);
- }
-
- public int read(CharBuffer target) throws IOException {
- if (timesRead == 1) {
- target.append('1');
- target.append('2');
- target.append('3');
- timesRead++;
- return 3;
- } else if (timesRead == 2) {
- target.append('t');
- timesRead++;
- return 1;
- } else {
- throw new IOException();
- }
- }
+ 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/OldTimeZoneTest.java b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
index 03a49ca..713e1b5 100644
--- a/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/OldTimeZoneTest.java
@@ -22,7 +22,6 @@
import java.util.Locale;
import java.util.TimeZone;
import junit.framework.TestCase;
-import tests.support.Support_Locale;
public class OldTimeZoneTest extends TestCase {
@@ -93,10 +92,7 @@
public void test_getDisplayNameLjava_util_Locale() {
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
assertEquals("Pacific Standard Time", tz.getDisplayName(new Locale("US")));
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- // BEGIN android-note: RI has "Heure", CLDR/ICU has "heure".
- assertEquals("heure normale du Pacifique", tz.getDisplayName(Locale.FRANCE));
- }
+ assertEquals("heure normale du Pacifique", tz.getDisplayName(Locale.FRANCE));
}
public void test_getDisplayNameZI() {
@@ -112,16 +108,12 @@
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
assertEquals("PST", tz.getDisplayName(false, 0, Locale.US));
assertEquals("Pacific Daylight Time", tz.getDisplayName(true, 1, Locale.US));
- if (Support_Locale.isLocaleAvailable(Locale.UK)) {
- assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1, Locale.UK));
- }
- if (Support_Locale.isLocaleAvailable(Locale.FRANCE)) {
- // RI always returns short time zone name as "PST"
- // ICU zone/root.txt patched to allow metazone names.
- assertEquals("PST", tz.getDisplayName(false, 0, Locale.FRANCE));
- assertEquals("heure avanc\u00e9e du Pacifique", tz.getDisplayName(true, 1, Locale.FRANCE));
- assertEquals("heure normale du Pacifique", tz.getDisplayName(false, 1, Locale.FRANCE));
- }
+ assertEquals("Pacific Standard Time", tz.getDisplayName(false, 1, Locale.UK));
+ // RI always returns short time zone name as "PST"
+ // ICU zone/root.txt patched to allow metazone names.
+ assertEquals("PST", tz.getDisplayName(false, 0, Locale.FRANCE));
+ assertEquals("heure avanc\u00e9e du Pacifique", tz.getDisplayName(true, 1, Locale.FRANCE));
+ assertEquals("heure normale du Pacifique", tz.getDisplayName(false, 1, Locale.FRANCE));
}
public void test_getID() {
diff --git a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
index 8d6e186..deb0626 100644
--- a/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
+++ b/luni/src/test/java/libcore/java/util/regex/OldMatcherTest.java
@@ -421,44 +421,6 @@
}
- // BEGIN android-note
- // Test took ages, now going in steps of 16 code points to speed things up.
- // END android-note
- public void testAllCodePoints() {
- // Regression for HARMONY-3145
- int[] codePoint = new int[1];
- Pattern p = Pattern.compile("(\\p{all})+");
- boolean res = true;
- int cnt = 0;
- String s;
- for (int i = 0; i < 0x110000; i = i + 0x10) {
- codePoint[0] = i;
- s = new String(codePoint, 0, 1);
- if (!s.matches(p.toString())) {
- cnt++;
- res = false;
- }
- }
- assertTrue(res);
- assertEquals(0, cnt);
-
- p = Pattern.compile("(\\P{all})+");
- res = true;
- cnt = 0;
-
- for (int i = 0; i < 0x110000; i = i + 0x10) {
- codePoint[0] = i;
- s = new String(codePoint, 0, 1);
- if (!s.matches(p.toString())) {
- cnt++;
- res = false;
- }
- }
-
- assertFalse(res);
- assertEquals(0x110000 / 0x10, cnt);
- }
-
public void test_regionStart() {
String testPattern = "(abb)";
String testString = "cccabbabbabbabbabb";
diff --git a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
index 37d1248..2e32f7d 100644
--- a/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/DeflaterOutputStreamTest.java
@@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
+import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PipedInputStream;
@@ -30,13 +31,15 @@
import java.util.concurrent.Executors;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
import java.util.zip.InflaterInputStream;
import junit.framework.TestCase;
public class DeflaterOutputStreamTest extends TestCase {
public void testSyncFlushEnabled() throws Exception {
- InflaterInputStream in = createInflaterStream(true);
+ InputStream in = createInflaterStream(DeflaterOutputStream.class, true);
assertEquals(1, in.read());
assertEquals(2, in.read());
assertEquals(3, in.read());
@@ -44,7 +47,7 @@
}
public void testSyncFlushDisabled() throws Exception {
- InflaterInputStream in = createInflaterStream(false);
+ InputStream in = createInflaterStream(DeflaterOutputStream.class, false);
try {
in.read();
fail();
@@ -65,14 +68,21 @@
* way demonstrate that data is unavailable. Ie. other techniques will cause
* the dry read to block indefinitely.
*/
- private InflaterInputStream createInflaterStream(final boolean flushing) throws Exception {
+ static InputStream createInflaterStream(final Class<?> c, final boolean flushing) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
final PipedOutputStream pout = new PipedOutputStream();
PipedInputStream pin = new PipedInputStream(pout);
executor.submit(new Callable<Void>() {
public Void call() throws Exception {
- OutputStream out = new DeflaterOutputStream(pout, flushing);
+ OutputStream out;
+ if (c == DeflaterOutputStream.class) {
+ out = new DeflaterOutputStream(pout, flushing);
+ } else if (c == GZIPOutputStream.class) {
+ out = new GZIPOutputStream(pout, flushing);
+ } else {
+ throw new AssertionError();
+ }
out.write(1);
out.write(2);
out.write(3);
@@ -82,7 +92,13 @@
}).get();
executor.shutdown();
- return new InflaterInputStream(pin);
+ if (c == DeflaterOutputStream.class) {
+ return new InflaterInputStream(pin);
+ } else if (c == GZIPOutputStream.class) {
+ return new GZIPInputStream(pin);
+ } else {
+ throw new AssertionError();
+ }
}
/**
@@ -146,5 +162,9 @@
// during the test, since that would lead to the results being
// flushed even without SYNC_FLUSH being used
assertFalse(def.finished());
+
+ // Quieten CloseGuard.
+ def.end();
+ iis.close();
}
}
diff --git a/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java b/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
index a61880f..55e45bc 100644
--- a/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/GZIPOutputStreamTest.java
@@ -25,26 +25,46 @@
import java.util.Random;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
+import java.util.zip.InflaterInputStream;
import junit.framework.TestCase;
public final class GZIPOutputStreamTest extends TestCase {
- public void testShortMessage() throws IOException {
- byte[] data = gzip(("Hello World").getBytes("UTF-8"));
- assertEquals("[31, -117, 8, 0, 0, 0, 0, 0, 0, 0, -13, 72, -51, -55, -55, 87, 8, -49, " +
- "47, -54, 73, 1, 0, 86, -79, 23, 74, 11, 0, 0, 0]", Arrays.toString(data));
- }
+ public void testShortMessage() throws IOException {
+ byte[] data = gzip(("Hello World").getBytes("UTF-8"));
+ assertEquals("[31, -117, 8, 0, 0, 0, 0, 0, 0, 0, -13, 72, -51, -55, -55, 87, 8, -49, " +
+ "47, -54, 73, 1, 0, 86, -79, 23, 74, 11, 0, 0, 0]", Arrays.toString(data));
+ }
- public void testLongMessage() throws IOException {
- byte[] data = new byte[1024 * 1024];
- new Random().nextBytes(data);
- assertTrue(Arrays.equals(data, GZIPInputStreamTest.gunzip(gzip(data))));
- }
+ public void testLongMessage() throws IOException {
+ byte[] data = new byte[1024 * 1024];
+ new Random().nextBytes(data);
+ assertTrue(Arrays.equals(data, GZIPInputStreamTest.gunzip(gzip(data))));
+ }
- public static byte[] gzip(byte[] bytes) throws IOException {
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
- gzippedOut.write(bytes);
- gzippedOut.close();
- return bytesOut.toByteArray();
+ public static byte[] gzip(byte[] bytes) throws IOException {
+ ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
+ OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
+ gzippedOut.write(bytes);
+ gzippedOut.close();
+ return bytesOut.toByteArray();
+ }
+
+ public void testSyncFlushEnabled() throws Exception {
+ InputStream in = DeflaterOutputStreamTest.createInflaterStream(GZIPOutputStream.class, true);
+ assertEquals(1, in.read());
+ assertEquals(2, in.read());
+ assertEquals(3, in.read());
+ in.close();
+ }
+
+ public void testSyncFlushDisabled() throws Exception {
+ InputStream in = DeflaterOutputStreamTest.createInflaterStream(GZIPOutputStream.class, false);
+ try {
+ in.read();
+ fail();
+ } catch (IOException expected) {
}
+ in.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 b1fa33c..cad881b 100644
--- a/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
+++ b/luni/src/test/java/libcore/java/util/zip/ZipFileTest.java
@@ -316,7 +316,7 @@
return sb.toString();
}
- public void testComment() throws Exception {
+ public void testComments() throws Exception {
String expectedFileComment = "1 \u0666 2";
String expectedEntryComment = "a \u0666 b";
@@ -361,11 +361,23 @@
out.close();
ZipFile zipFile = new ZipFile(file);
- // TODO: there's currently no API for reading the file comment --- strings(1) the file?
+ assertEquals(expectedFileComment, zipFile.getComment());
assertEquals(expectedEntryComment, zipFile.getEntry("a").getComment());
zipFile.close();
}
+ public void test_getComment_unset() throws Exception {
+ File file = createTemporaryZipFile();
+ ZipOutputStream out = createZipOutputStream(file);
+ ZipEntry ze = new ZipEntry("test entry");
+ ze.setComment("per-entry comment");
+ out.putNextEntry(ze);
+ out.close();
+
+ ZipFile zipFile = new ZipFile(file);
+ 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.
diff --git a/luni/src/test/java/libcore/javax/crypto/CipherTest.java b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
index 4054813..dac43a2 100644
--- a/luni/src/test/java/libcore/javax/crypto/CipherTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/CipherTest.java
@@ -20,6 +20,7 @@
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.math.BigInteger;
+import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
@@ -91,28 +92,28 @@
IS_UNLIMITED = is_unlimited;
}
- private static boolean isUnsupported(String algorithm, String provider) {
+ private static boolean isSupported(String algorithm, String provider) {
if (algorithm.equals("RC2")) {
- return true;
+ return false;
}
if (algorithm.equals("PBEWITHMD5ANDRC2")) {
- return true;
+ return false;
}
if (algorithm.startsWith("PBEWITHSHA1ANDRC2")) {
- return true;
+ return false;
}
if (algorithm.equals("PBEWITHSHAAND40BITRC2-CBC")) {
- return true;
+ return false;
}
if (algorithm.equals("PBEWITHSHAAND128BITRC2-CBC")) {
- return true;
+ return false;
}
if (algorithm.equals("PBEWITHSHAANDTWOFISH-CBC")) {
- return true;
+ return false;
}
if (!IS_UNLIMITED) {
if (algorithm.equals("PBEWITHMD5ANDTRIPLEDES")) {
- return true;
+ return false;
}
}
// stream modes CFB, CTR, CTS, OFB with PKCS5Padding don't really make sense
@@ -121,25 +122,25 @@
|| algorithm.equals("AES/CTR/PKCS5PADDING")
|| algorithm.equals("AES/CTS/PKCS5PADDING")
|| algorithm.equals("AES/OFB/PKCS5PADDING"))) {
- return true;
+ return false;
}
- return false;
+ return true;
}
- private static boolean isUnsupportedForWrapping(String algorithm) {
+ private static boolean isSupportedForWrapping(String algorithm) {
if (isOnlyWrappingAlgorithm(algorithm)) {
- return false;
+ return true;
}
// http://b/9097343 RSA with NoPadding won't work since
// leading zeroes in the underlying key material are lost.
if (algorithm.equals("RSA/ECB/NOPADDING")) {
- return true;
+ return false;
}
// AESWRAP should be used instead, fails with BC and SunJCE otherwise.
if (algorithm.startsWith("AES")) {
- return true;
+ return false;
}
- return false;
+ return true;
}
private synchronized static int getEncryptMode(String algorithm) throws Exception {
@@ -796,7 +797,7 @@
private void test_Cipher(Cipher c) throws Exception {
String algorithm = c.getAlgorithm().toUpperCase(Locale.US);
String providerName = c.getProvider().getName();
- if (isUnsupported(algorithm, providerName)) {
+ if (!isSupported(algorithm, providerName)) {
return;
}
String cipherID = algorithm + ":" + providerName;
@@ -832,7 +833,7 @@
assertNull(cipherID, c.getExemptionMechanism());
// Test wrapping a key. Every cipher should be able to wrap. Except those that can't.
- if (!isUnsupportedForWrapping(algorithm)) {
+ if (isSupportedForWrapping(algorithm)) {
// Generate a small SecretKey for AES.
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128);
@@ -2164,6 +2165,12 @@
c.init(Cipher.DECRYPT_MODE, key, spec);
+ try {
+ c.updateAAD(new byte[8]);
+ fail("Cipher should not support AAD");
+ } catch (UnsupportedOperationException expected) {
+ }
+
byte[] emptyPlainText = c.doFinal(emptyCipherText);
assertEquals(Arrays.toString(EmptyArray.BYTE), Arrays.toString(emptyPlainText));
@@ -2257,6 +2264,82 @@
}
}
+ public void testCipher_updateAAD_BeforeInit_Failure() throws Exception {
+ Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
+
+ try {
+ c.updateAAD((byte[]) null);
+ fail("should not be able to call updateAAD before Cipher is initialized");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD((ByteBuffer) null);
+ fail("should not be able to call updateAAD before Cipher is initialized");
+ } catch (IllegalStateException expected) {
+ }
+
+ try {
+ c.updateAAD(new byte[8]);
+ fail("should not be able to call updateAAD before Cipher is initialized");
+ } catch (IllegalStateException expected) {
+ }
+
+ try {
+ c.updateAAD(null, 0, 8);
+ fail("should not be able to call updateAAD before Cipher is initialized");
+ } catch (IllegalStateException expected) {
+ }
+
+ ByteBuffer bb = ByteBuffer.allocate(8);
+ try {
+ c.updateAAD(bb);
+ fail("should not be able to call updateAAD before Cipher is initialized");
+ } catch (IllegalStateException expected) {
+ }
+ }
+
+ public void testCipher_updateAAD_AfterInit_Failure() throws Exception {
+ Cipher c = Cipher.getInstance("AES/ECB/NoPadding");
+ c.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(new byte[128 / 8], "AES"));
+
+ try {
+ c.updateAAD((byte[]) null);
+ fail("should not be able to call updateAAD with null input");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD((ByteBuffer) null);
+ fail("should not be able to call updateAAD with null input");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD(null, 0, 8);
+ fail("should not be able to call updateAAD with null input");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD(new byte[8], -1, 7);
+ fail("should not be able to call updateAAD with invalid offset");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD(new byte[8], 0, -1);
+ fail("should not be able to call updateAAD with negative length");
+ } catch (IllegalArgumentException expected) {
+ }
+
+ try {
+ c.updateAAD(new byte[8], 0, 8 + 1);
+ fail("should not be able to call updateAAD with too large length");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
public void testCipher_ShortBlock_Failure() throws Exception {
for (String provider : AES_PROVIDERS) {
testCipher_ShortBlock_Failure(provider);
diff --git a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
index 7519aab..ef5adc9 100644
--- a/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/SecretKeyFactoryTest.java
@@ -23,6 +23,7 @@
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import junit.framework.TestCase;
+import libcore.java.security.StandardNames;
public class SecretKeyFactoryTest extends TestCase {
@@ -107,13 +108,14 @@
}
public void test_PBKDF2_b3059950() throws Exception {
- test_PBKDF2(PASSWORD, SALT, ITERATIONS, KEY_LENGTH,
- new byte[] {
+ byte[] expected = new byte[] {
(byte)0x70, (byte)0x74, (byte)0xdb, (byte)0x72,
(byte)0x35, (byte)0xd4, (byte)0x11, (byte)0x68,
(byte)0x83, (byte)0x7c, (byte)0x14, (byte)0x1f,
(byte)0xf6, (byte)0x4a, (byte)0xb0, (byte)0x54
- });
+ };
+ test_PBKDF2_UTF8(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected);
+ test_PBKDF2_8BIT(PASSWORD, SALT, ITERATIONS, KEY_LENGTH, expected);
}
/**
@@ -133,7 +135,8 @@
(byte)0xD1, (byte)0xDA, (byte)0xA7, (byte)0x86,
(byte)0x15, (byte)0xF2, (byte)0x87, (byte)0xE6
};
- test_PBKDF2(password, salt, iterations, keyLength, expected);
+ test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected);
+ test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected);
}
/**
@@ -156,11 +159,50 @@
(byte)0x85, (byte)0x10, (byte)0x85, (byte)0x86, (byte)0x07, (byte)0x12,
(byte)0x63, (byte)0x80, (byte)0xcc, (byte)0x47, (byte)0xab, (byte)0x2d
};
- test_PBKDF2(password, salt, iterations, keyLength, expected);
+ test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected);
+ test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected);
}
- private void test_PBKDF2(char[] password, byte[] salt, int iterations, int keyLength,
- byte[] expected) throws Exception {
+ /**
+ * Unicode Test vector for b/8312059.
+ *
+ * See also https://code.google.com/p/android/issues/detail?id=40578
+ */
+ public void test_PBKDF2_b8312059() throws Exception {
+
+ char[] password = "\u0141\u0142".toCharArray();
+ byte[] salt = "salt".getBytes();
+ int iterations = 4096;
+ int keyLength = 160;
+ byte[] expected_utf8 = new byte[] {
+ (byte)0x4c, (byte)0xe0, (byte)0x6a, (byte)0xb8, (byte)0x48, (byte)0x04,
+ (byte)0xb7, (byte)0xe7, (byte)0x72, (byte)0xf2, (byte)0xaf, (byte)0x5e,
+ (byte)0x54, (byte)0xe9, (byte)0x03, (byte)0xad, (byte)0x59, (byte)0x64,
+ (byte)0x8b, (byte)0xab
+ };
+ byte[] expected_8bit = new byte[] {
+ (byte)0x6e, (byte)0x43, (byte)0xe0, (byte)0x18, (byte)0xc5, (byte)0x50,
+ (byte)0x0d, (byte)0xa7, (byte)0xfe, (byte)0x7a, (byte)0x44, (byte)0x4d,
+ (byte)0x99, (byte)0x5d, (byte)0x8c, (byte)0xae, (byte)0xc1, (byte)0xc9,
+ (byte)0x17, (byte)0xce
+ };
+ test_PBKDF2_UTF8(password, salt, iterations, keyLength, expected_utf8);
+ test_PBKDF2_8BIT(password, salt, iterations, keyLength, expected_8bit);
+ }
+
+ private void test_PBKDF2_8BIT(char[] password, byte[] salt, int iterations, int keyLength,
+ byte[] expected) throws Exception {
+ if (!StandardNames.IS_RI) {
+ SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1And8bit");
+ KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength);
+ SecretKey key = factory.generateSecret(ks);
+ assertTrue(Arrays.equals(expected, key.getEncoded()));
+ }
+
+ }
+
+ private void test_PBKDF2_UTF8(char[] password, byte[] salt, int iterations, int keyLength,
+ byte[] expected) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec ks = new PBEKeySpec(password, salt, iterations, keyLength);
SecretKey key = factory.generateSecret(ks);
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
index 69ae1c1..e1c9fe3 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
@@ -19,7 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigInteger;
-import java.nio.charset.Charsets;
+import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
@@ -301,7 +301,7 @@
}
X509Certificate parseCertificate(String encoded) throws Exception {
- InputStream in = new ByteArrayInputStream(encoded.getBytes(Charsets.US_ASCII));
+ InputStream in = new ByteArrayInputStream(encoded.getBytes(StandardCharsets.US_ASCII));
return (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(in);
}
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 7a1465e..de12967 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -1215,7 +1215,7 @@
client.startHandshake();
// Reflection is used so this can compile on the RI
- String expectedClassName = "org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl";
+ String expectedClassName = "com.android.org.conscrypt.OpenSSLSocketImpl";
Class actualClass = client.getClass();
assertEquals(expectedClassName, actualClass.getName());
Method setSoWriteTimeout = actualClass.getMethod("setSoWriteTimeout",
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index e37ed1f..7ee5778 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -19,10 +19,12 @@
import java.io.ByteArrayInputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.util.Arrays;
import javax.security.auth.x500.X500Principal;
import junit.framework.TestCase;
import libcore.util.SerializationTester;
+
public class X500PrincipalTest extends TestCase {
public void testSerialization() {
@@ -90,4 +92,23 @@
certBC.getSubjectX500Principal().getName(X500Principal.CANONICAL));
}
+
+ // http://code.google.com/p/android/issues/detail?id=21531
+ // http://b/5580664
+ public void testIA5StringEncodings() {
+ testIA5StringEncoding("emailAddress=root@android.com",
+ new byte[] { 48, 33, 49, 31, 48, 29, 6, 9, 42, -122, 72, -122, -9, 13, 1, 9, 1, 22, 16, 114, 111, 111, 116, 64, 97, 110, 100, 114, 111, 105, 100, 46, 99, 111, 109 });
+ testIA5StringEncoding("dc=com",
+ new byte[] { 48, 21, 49, 19, 48, 17, 6, 10, 9, -110, 38, -119, -109, -14, 44, 100, 1, 25, 22, 3, 99, 111, 109 });
+ }
+
+ private void testIA5StringEncoding(String name, byte[] expectedEncoded) {
+ X500Principal original = new X500Principal(name);
+
+ byte[] actualEncoded = original.getEncoded();
+ assertEquals(Arrays.toString(expectedEncoded), Arrays.toString(actualEncoded));
+
+ X500Principal decoded = new X500Principal(actualEncoded);
+ assertEquals(original, decoded);
+ }
}
diff --git a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java b/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
deleted file mode 100644
index 133924e..0000000
--- a/luni/src/test/java/libcore/net/http/HttpResponseCacheTest.java
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
- * 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 libcore.net.http;
-
-import com.google.mockwebserver.MockResponse;
-import com.google.mockwebserver.MockWebServer;
-import com.google.mockwebserver.RecordedRequest;
-import static com.google.mockwebserver.SocketPolicy.DISCONNECT_AT_END;
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.InvocationHandler;
-import java.net.CacheRequest;
-import java.net.CacheResponse;
-import java.net.CookieHandler;
-import java.net.CookieManager;
-import java.net.HttpCookie;
-import java.net.HttpURLConnection;
-import java.net.ResponseCache;
-import java.net.SecureCacheResponse;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.security.Principal;
-import java.security.cert.Certificate;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Deque;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.UUID;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.zip.GZIPOutputStream;
-import javax.net.ssl.HttpsURLConnection;
-import junit.framework.TestCase;
-import libcore.javax.net.ssl.TestSSLContext;
-import tests.io.MockOs;
-
-public final class HttpResponseCacheTest extends TestCase {
- private MockWebServer server = new MockWebServer();
- private HttpResponseCache cache;
- private final MockOs mockOs = new MockOs();
- private final CookieManager cookieManager = new CookieManager();
-
- @Override protected void setUp() throws Exception {
- super.setUp();
-
- String tmp = System.getProperty("java.io.tmpdir");
- File cacheDir = new File(tmp, "HttpCache-" + UUID.randomUUID());
- cache = new HttpResponseCache(cacheDir, Integer.MAX_VALUE);
- ResponseCache.setDefault(cache);
- mockOs.install();
- CookieHandler.setDefault(cookieManager);
- }
-
- @Override protected void tearDown() throws Exception {
- mockOs.uninstall();
- server.shutdown();
- ResponseCache.setDefault(null);
- cache.getCache().delete();
- CookieHandler.setDefault(null);
- super.tearDown();
- }
-
- /**
- * Test that response caching is consistent with the RI and the spec.
- * http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4
- */
- public void testResponseCachingByResponseCode() throws Exception {
- // Test each documented HTTP/1.1 code, plus the first unused value in each range.
- // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
-
- // We can't test 100 because it's not really a response.
- // assertCached(false, 100);
- assertCached(false, 101);
- assertCached(false, 102);
- assertCached(true, 200);
- assertCached(false, 201);
- assertCached(false, 202);
- assertCached(true, 203);
- assertCached(false, 204);
- assertCached(false, 205);
- assertCached(false, 206); // we don't cache partial responses
- assertCached(false, 207);
- assertCached(true, 300);
- assertCached(true, 301);
- for (int i = 302; i <= 308; ++i) {
- assertCached(false, i);
- }
- for (int i = 400; i <= 406; ++i) {
- assertCached(false, i);
- }
- // (See test_responseCaching_407.)
- assertCached(false, 408);
- assertCached(false, 409);
- // (See test_responseCaching_410.)
- for (int i = 411; i <= 418; ++i) {
- assertCached(false, i);
- }
- for (int i = 500; i <= 506; ++i) {
- assertCached(false, i);
- }
- }
-
- /**
- * Response code 407 should only come from proxy servers. Android's client
- * throws if it is sent by an origin server.
- */
- public void testOriginServerSends407() throws Exception {
- server.enqueue(new MockResponse().setResponseCode(407));
- server.play();
-
- URL url = server.getUrl("/");
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- try {
- conn.getResponseCode();
- fail();
- } catch (IOException expected) {
- }
- }
-
- public void test_responseCaching_410() throws Exception {
- // the HTTP spec permits caching 410s, but the RI doesn't.
- assertCached(true, 410);
- }
-
- private void assertCached(boolean shouldPut, int responseCode) throws Exception {
- server = new MockWebServer();
- MockResponse response = new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setResponseCode(responseCode)
- .setBody("ABCDE")
- .addHeader("WWW-Authenticate: challenge");
- if (responseCode == HttpURLConnection.HTTP_PROXY_AUTH) {
- response.addHeader("Proxy-Authenticate: Basic realm=\"protected area\"");
- } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
- response.addHeader("WWW-Authenticate: Basic realm=\"protected area\"");
- }
- server.enqueue(response);
- server.play();
-
- URL url = server.getUrl("/");
- HttpURLConnection conn = (HttpURLConnection) url.openConnection();
- assertEquals(responseCode, conn.getResponseCode());
-
- // exhaust the content stream
- readAscii(conn);
-
- CacheResponse cached = cache.get(url.toURI(), "GET",
- Collections.<String, List<String>>emptyMap());
- if (shouldPut) {
- assertNotNull(Integer.toString(responseCode), cached);
- cached.getBody().close();
- } else {
- assertNull(Integer.toString(responseCode), cached);
- }
- server.shutdown(); // tearDown() isn't sufficient; this test starts multiple servers
- }
-
- /**
- * Test that we can interrogate the response when the cache is being
- * populated. http://code.google.com/p/android/issues/detail?id=7787
- */
- public void testResponseCacheCallbackApis() throws Exception {
- final String body = "ABCDE";
- final AtomicInteger cacheCount = new AtomicInteger();
-
- server.enqueue(new MockResponse()
- .setStatus("HTTP/1.1 200 Fantastic")
- .addHeader("fgh: ijk")
- .setBody(body));
- server.play();
-
- ResponseCache.setDefault(new ResponseCache() {
- @Override public CacheResponse get(URI uri, String requestMethod,
- Map<String, List<String>> requestHeaders) throws IOException {
- return null;
- }
- @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
- HttpURLConnection httpConnection = (HttpURLConnection) conn;
- try {
- httpConnection.getRequestProperties();
- fail();
- } catch (IllegalStateException expected) {
- }
- try {
- httpConnection.addRequestProperty("K", "V");
- fail();
- } catch (IllegalStateException expected) {
- }
- assertEquals("HTTP/1.1 200 Fantastic", httpConnection.getHeaderField(null));
- assertEquals(Arrays.asList("HTTP/1.1 200 Fantastic"),
- httpConnection.getHeaderFields().get(null));
- assertEquals(200, httpConnection.getResponseCode());
- assertEquals("Fantastic", httpConnection.getResponseMessage());
- assertEquals(body.length(), httpConnection.getContentLength());
- assertEquals("ijk", httpConnection.getHeaderField("fgh"));
- try {
- httpConnection.getInputStream(); // the RI doesn't forbid this, but it should
- fail();
- } catch (IOException expected) {
- }
- cacheCount.incrementAndGet();
- return null;
- }
- });
-
- URL url = server.getUrl("/");
- URLConnection connection = url.openConnection();
- assertEquals(body, readAscii(connection));
- assertEquals(1, cacheCount.get());
- }
-
-
- public void testResponseCachingAndInputStreamSkipWithFixedLength() throws IOException {
- testResponseCaching(TransferKind.FIXED_LENGTH);
- }
-
- public void testResponseCachingAndInputStreamSkipWithChunkedEncoding() throws IOException {
- testResponseCaching(TransferKind.CHUNKED);
- }
-
- public void testResponseCachingAndInputStreamSkipWithNoLengthHeaders() throws IOException {
- testResponseCaching(TransferKind.END_OF_STREAM);
- }
-
- /**
- * HttpURLConnection.getInputStream().skip(long) causes ResponseCache corruption
- * http://code.google.com/p/android/issues/detail?id=8175
- */
- private void testResponseCaching(TransferKind transferKind) throws IOException {
- MockResponse response = new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setStatus("HTTP/1.1 200 Fantastic");
- transferKind.setBody(response, "I love puppies but hate spiders", 1);
- server.enqueue(response);
- server.play();
-
- // Make sure that calling skip() doesn't omit bytes from the cache.
- HttpURLConnection urlConnection = (HttpURLConnection) server.getUrl("/").openConnection();
- InputStream in = urlConnection.getInputStream();
- assertEquals("I love ", readAscii(urlConnection, "I love ".length()));
- reliableSkip(in, "puppies but hate ".length());
- assertEquals("spiders", readAscii(urlConnection, "spiders".length()));
- assertEquals(-1, in.read());
- in.close();
- assertEquals(1, cache.getWriteSuccessCount());
- assertEquals(0, cache.getWriteAbortCount());
-
- urlConnection = (HttpURLConnection) server.getUrl("/").openConnection(); // cached!
- in = urlConnection.getInputStream();
- assertEquals("I love puppies but hate spiders",
- readAscii(urlConnection, "I love puppies but hate spiders".length()));
- assertEquals(200, urlConnection.getResponseCode());
- assertEquals("Fantastic", urlConnection.getResponseMessage());
-
- assertEquals(-1, in.read());
- in.close();
- assertEquals(1, cache.getWriteSuccessCount());
- assertEquals(0, cache.getWriteAbortCount());
- assertEquals(2, cache.getRequestCount());
- assertEquals(1, cache.getHitCount());
- }
-
- public void testSecureResponseCaching() throws IOException {
- TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setBody("ABC"));
- server.play();
-
- HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("ABC", readAscii(connection));
-
- // OpenJDK 6 fails on this line, complaining that the connection isn't open yet
- String suite = connection.getCipherSuite();
- List<Certificate> localCerts = toListOrNull(connection.getLocalCertificates());
- List<Certificate> serverCerts = toListOrNull(connection.getServerCertificates());
- Principal peerPrincipal = connection.getPeerPrincipal();
- Principal localPrincipal = connection.getLocalPrincipal();
-
- connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("ABC", readAscii(connection));
-
- assertEquals(2, cache.getRequestCount());
- assertEquals(1, cache.getNetworkCount());
- assertEquals(1, cache.getHitCount());
-
- assertEquals(suite, connection.getCipherSuite());
- assertEquals(localCerts, toListOrNull(connection.getLocalCertificates()));
- assertEquals(serverCerts, toListOrNull(connection.getServerCertificates()));
- assertEquals(peerPrincipal, connection.getPeerPrincipal());
- assertEquals(localPrincipal, connection.getLocalPrincipal());
- }
-
- public void testCacheReturnsInsecureResponseForSecureRequest() throws IOException {
- TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
- server.enqueue(new MockResponse().setBody("ABC"));
- server.enqueue(new MockResponse().setBody("DEF"));
- server.play();
-
- ResponseCache.setDefault(new InsecureResponseCache());
-
- HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("ABC", readAscii(connection));
-
- connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // not cached!
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("DEF", readAscii(connection));
- }
-
- public void testResponseCachingAndRedirects() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
- .addHeader("Location: /foo"));
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setBody("ABC"));
- server.enqueue(new MockResponse().setBody("DEF"));
- server.play();
-
- URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("ABC", readAscii(connection));
-
- connection = server.getUrl("/").openConnection(); // cached!
- assertEquals("ABC", readAscii(connection));
-
- assertEquals(4, cache.getRequestCount()); // 2 requests + 2 redirects
- assertEquals(2, cache.getNetworkCount());
- assertEquals(2, cache.getHitCount());
- }
-
- public void testRedirectToCachedResult() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .setBody("ABC"));
- server.enqueue(new MockResponse()
- .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
- .addHeader("Location: /foo"));
- server.enqueue(new MockResponse().setBody("DEF"));
- server.play();
-
- assertEquals("ABC", readAscii(server.getUrl("/foo").openConnection()));
- RecordedRequest request1 = server.takeRequest();
- assertEquals("GET /foo HTTP/1.1", request1.getRequestLine());
- assertEquals(0, request1.getSequenceNumber());
-
- assertEquals("ABC", readAscii(server.getUrl("/bar").openConnection()));
- RecordedRequest request2 = server.takeRequest();
- assertEquals("GET /bar HTTP/1.1", request2.getRequestLine());
- assertEquals(1, request2.getSequenceNumber());
-
- // an unrelated request should reuse the pooled connection
- assertEquals("DEF", readAscii(server.getUrl("/baz").openConnection()));
- RecordedRequest request3 = server.takeRequest();
- assertEquals("GET /baz HTTP/1.1", request3.getRequestLine());
- assertEquals(2, request3.getSequenceNumber());
- }
-
- public void testSecureResponseCachingAndRedirects() throws IOException {
- TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setResponseCode(HttpURLConnection.HTTP_MOVED_PERM)
- .addHeader("Location: /foo"));
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .setBody("ABC"));
- server.enqueue(new MockResponse().setBody("DEF"));
- server.play();
-
- HttpsURLConnection connection = (HttpsURLConnection) server.getUrl("/").openConnection();
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("ABC", readAscii(connection));
-
- connection = (HttpsURLConnection) server.getUrl("/").openConnection(); // cached!
- connection.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- assertEquals("ABC", readAscii(connection));
-
- assertEquals(4, cache.getRequestCount()); // 2 direct + 2 redirect = 4
- assertEquals(2, cache.getHitCount());
- }
-
- public void testResponseCacheRequestHeaders() throws IOException, URISyntaxException {
- server.enqueue(new MockResponse().setBody("ABC"));
- server.play();
-
- final AtomicReference<Map<String, List<String>>> requestHeadersRef
- = new AtomicReference<Map<String, List<String>>>();
- ResponseCache.setDefault(new ResponseCache() {
- @Override public CacheResponse get(URI uri, String requestMethod,
- Map<String, List<String>> requestHeaders) throws IOException {
- requestHeadersRef.set(requestHeaders);
- return null;
- }
- @Override public CacheRequest put(URI uri, URLConnection conn) throws IOException {
- return null;
- }
- });
-
- URL url = server.getUrl("/");
- URLConnection urlConnection = url.openConnection();
- urlConnection.addRequestProperty("A", "android");
- readAscii(urlConnection);
- assertEquals(Arrays.asList("android"), requestHeadersRef.get().get("A"));
- }
-
-
- public void testServerDisconnectsPrematurelyWithContentLengthHeader() throws IOException {
- testServerPrematureDisconnect(TransferKind.FIXED_LENGTH);
- }
-
- public void testServerDisconnectsPrematurelyWithChunkedEncoding() throws IOException {
- testServerPrematureDisconnect(TransferKind.CHUNKED);
- }
-
- public void testServerDisconnectsPrematurelyWithNoLengthHeaders() throws IOException {
- /*
- * Intentionally empty. This case doesn't make sense because there's no
- * such thing as a premature disconnect when the disconnect itself
- * indicates the end of the data stream.
- */
- }
-
- private void testServerPrematureDisconnect(TransferKind transferKind) throws IOException {
- MockResponse response = new MockResponse();
- transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 16);
- server.enqueue(truncateViolently(response, 16));
- server.enqueue(new MockResponse().setBody("Request #2"));
- server.play();
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- server.getUrl("/").openConnection().getInputStream()));
- assertEquals("ABCDE", reader.readLine());
- try {
- reader.readLine();
- fail("This implementation silently ignored a truncated HTTP body.");
- } catch (IOException expected) {
- } finally {
- reader.close();
- }
-
- assertEquals(1, cache.getWriteAbortCount());
- assertEquals(0, cache.getWriteSuccessCount());
- URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("Request #2", readAscii(connection));
- assertEquals(1, cache.getWriteAbortCount());
- assertEquals(1, cache.getWriteSuccessCount());
- }
-
- public void testClientPrematureDisconnectWithContentLengthHeader() throws IOException {
- testClientPrematureDisconnect(TransferKind.FIXED_LENGTH);
- }
-
- public void testClientPrematureDisconnectWithChunkedEncoding() throws IOException {
- testClientPrematureDisconnect(TransferKind.CHUNKED);
- }
-
- public void testClientPrematureDisconnectWithNoLengthHeaders() throws IOException {
- testClientPrematureDisconnect(TransferKind.END_OF_STREAM);
- }
-
- private void testClientPrematureDisconnect(TransferKind transferKind) throws IOException {
- MockResponse response = new MockResponse();
- transferKind.setBody(response, "ABCDE\nFGHIJKLMNOPQRSTUVWXYZ", 1024);
- server.enqueue(response);
- server.enqueue(new MockResponse().setBody("Request #2"));
- server.play();
-
- URLConnection connection = server.getUrl("/").openConnection();
- InputStream in = connection.getInputStream();
- assertEquals("ABCDE", readAscii(connection, 5));
- in.close();
- try {
- in.read();
- fail("Expected an IOException because the stream is closed.");
- } catch (IOException expected) {
- }
-
- assertEquals(1, cache.getWriteAbortCount());
- assertEquals(0, cache.getWriteSuccessCount());
- connection = server.getUrl("/").openConnection();
- assertEquals("Request #2", readAscii(connection));
- assertEquals(1, cache.getWriteAbortCount());
- assertEquals(1, cache.getWriteSuccessCount());
- }
-
- public void testDefaultExpirationDateFullyCachedForLessThan24Hours() throws Exception {
- // last modified: 105 seconds ago
- // served: 5 seconds ago
- // default lifetime: (105 - 5) / 10 = 10 seconds
- // expires: 10 seconds from served date = 5 seconds from now
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
- .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
- .setBody("A"));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- URLConnection connection = url.openConnection();
- assertEquals("A", readAscii(connection));
- assertNull(connection.getHeaderField("Warning"));
- }
-
- public void testDefaultExpirationDateConditionallyCached() throws Exception {
- // last modified: 115 seconds ago
- // served: 15 seconds ago
- // default lifetime: (115 - 15) / 10 = 10 seconds
- // expires: 10 seconds from served date = 5 seconds ago
- String lastModifiedDate = formatDate(-115, TimeUnit.SECONDS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Date: " + formatDate(-15, TimeUnit.SECONDS)));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testDefaultExpirationDateFullyCachedForMoreThan24Hours() throws Exception {
- // last modified: 105 days ago
- // served: 5 days ago
- // default lifetime: (105 - 5) / 10 = 10 days
- // expires: 10 days from served date = 5 days from now
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.DAYS))
- .addHeader("Date: " + formatDate(-5, TimeUnit.DAYS))
- .setBody("A"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- URLConnection connection = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection));
- assertEquals("113 HttpURLConnection \"Heuristic expiration\"",
- connection.getHeaderField("Warning"));
- }
-
- public void testNoDefaultExpirationForUrlsWithQueryString() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-105, TimeUnit.SECONDS))
- .addHeader("Date: " + formatDate(-5, TimeUnit.SECONDS))
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/?foo=bar");
- assertEquals("A", readAscii(url.openConnection()));
- assertEquals("B", readAscii(url.openConnection()));
- }
-
- public void testExpirationDateInThePastWithLastModifiedHeader() throws Exception {
- String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testExpirationDateInThePastWithNoLastModifiedHeader() throws Exception {
- assertNotCached(new MockResponse()
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
- }
-
- public void testExpirationDateInTheFuture() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
- }
-
- public void testMaxAgePreferredWithMaxAgeAndExpires() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgeInThePastWithDateAndLastModifiedHeaders() throws Exception {
- String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Cache-Control: max-age=60"));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testMaxAgeInThePastWithDateHeaderButNoLastModifiedHeader() throws Exception {
- /*
- * Chrome interprets max-age relative to the local clock. Both our cache
- * and Firefox both use the earlier of the local and server's clock.
- */
- assertNotCached(new MockResponse()
- .addHeader("Date: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgeInTheFutureWithDateHeader() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgeInTheFutureWithNoDateHeader() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgeWithLastModifiedButNoServedDate() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgeInTheFutureWithDateAndLastModifiedHeaders() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testMaxAgePreferredOverLowerSharedMaxAge() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
- .addHeader("Cache-Control: s-maxage=60")
- .addHeader("Cache-Control: max-age=180"));
- }
-
- public void testMaxAgePreferredOverHigherMaxAge() throws Exception {
- assertNotCached(new MockResponse()
- .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
- .addHeader("Cache-Control: s-maxage=180")
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testRequestMethodOptionsIsNotCached() throws Exception {
- testRequestMethod("OPTIONS", false);
- }
-
- public void testRequestMethodGetIsCached() throws Exception {
- testRequestMethod("GET", true);
- }
-
- public void testRequestMethodHeadIsNotCached() throws Exception {
- // We could support this but choose not to for implementation simplicity
- testRequestMethod("HEAD", false);
- }
-
- public void testRequestMethodPostIsNotCached() throws Exception {
- // We could support this but choose not to for implementation simplicity
- testRequestMethod("POST", false);
- }
-
- public void testRequestMethodPutIsNotCached() throws Exception {
- testRequestMethod("PUT", false);
- }
-
- public void testRequestMethodDeleteIsNotCached() throws Exception {
- testRequestMethod("DELETE", false);
- }
-
- public void testRequestMethodTraceIsNotCached() throws Exception {
- testRequestMethod("TRACE", false);
- }
-
- private void testRequestMethod(String requestMethod, boolean expectCached) throws Exception {
- /*
- * 1. seed the cache (potentially)
- * 2. expect a cache hit or miss
- */
- server.enqueue(new MockResponse()
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .addHeader("X-Response-ID: 1"));
- server.enqueue(new MockResponse()
- .addHeader("X-Response-ID: 2"));
- server.play();
-
- URL url = server.getUrl("/");
-
- HttpURLConnection request1 = (HttpURLConnection) url.openConnection();
- request1.setRequestMethod(requestMethod);
- addRequestBodyIfNecessary(requestMethod, request1);
- assertEquals("1", request1.getHeaderField("X-Response-ID"));
-
- URLConnection request2 = url.openConnection();
- if (expectCached) {
- assertEquals("1", request1.getHeaderField("X-Response-ID"));
- } else {
- assertEquals("2", request2.getHeaderField("X-Response-ID"));
- }
- }
-
- public void testPostInvalidatesCache() throws Exception {
- testMethodInvalidates("POST");
- }
-
- public void testPutInvalidatesCache() throws Exception {
- testMethodInvalidates("PUT");
- }
-
- public void testDeleteMethodInvalidatesCache() throws Exception {
- testMethodInvalidates("DELETE");
- }
-
- private void testMethodInvalidates(String requestMethod) throws Exception {
- /*
- * 1. seed the cache
- * 2. invalidate it
- * 3. expect a cache miss
- */
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
- server.enqueue(new MockResponse().setBody("B"));
- server.enqueue(new MockResponse().setBody("C"));
- server.play();
-
- URL url = server.getUrl("/");
-
- assertEquals("A", readAscii(url.openConnection()));
-
- HttpURLConnection invalidate = (HttpURLConnection) url.openConnection();
- invalidate.setRequestMethod(requestMethod);
- addRequestBodyIfNecessary(requestMethod, invalidate);
- assertEquals("B", readAscii(invalidate));
-
- assertEquals("C", readAscii(url.openConnection()));
- }
-
- public void testEtag() throws Exception {
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("ETag: v1"));
- assertTrue(conditionalRequest.getHeaders().contains("If-None-Match: v1"));
- }
-
- public void testEtagAndExpirationDateInThePast() throws Exception {
- String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("ETag: v1")
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-None-Match: v1"));
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testEtagAndExpirationDateInTheFuture() throws Exception {
- assertFullyCached(new MockResponse()
- .addHeader("ETag: v1")
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
- }
-
- public void testCacheControlNoCache() throws Exception {
- assertNotCached(new MockResponse().addHeader("Cache-Control: no-cache"));
- }
-
- public void testCacheControlNoCacheAndExpirationDateInTheFuture() throws Exception {
- String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .addHeader("Cache-Control: no-cache"));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testPragmaNoCache() throws Exception {
- assertNotCached(new MockResponse().addHeader("Pragma: no-cache"));
- }
-
- public void testPragmaNoCacheAndExpirationDateInTheFuture() throws Exception {
- String lastModifiedDate = formatDate(-2, TimeUnit.HOURS);
- RecordedRequest conditionalRequest = assertConditionallyCached(new MockResponse()
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .addHeader("Pragma: no-cache"));
- List<String> headers = conditionalRequest.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- public void testCacheControlNoStore() throws Exception {
- assertNotCached(new MockResponse().addHeader("Cache-Control: no-store"));
- }
-
- public void testCacheControlNoStoreAndExpirationDateInTheFuture() throws Exception {
- assertNotCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .addHeader("Cache-Control: no-store"));
- }
-
- public void testPartialRangeResponsesDoNotCorruptCache() throws Exception {
- /*
- * 1. request a range
- * 2. request a full document, expecting a cache miss
- */
- server.enqueue(new MockResponse().setBody("AA")
- .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS))
- .addHeader("Content-Range: bytes 1000-1001/2000"));
- server.enqueue(new MockResponse().setBody("BB"));
- server.play();
-
- URL url = server.getUrl("/");
-
- URLConnection range = url.openConnection();
- range.addRequestProperty("Range", "bytes=1000-1001");
- assertEquals("AA", readAscii(range));
-
- assertEquals("BB", readAscii(url.openConnection()));
- }
-
- public void testServerReturnsDocumentOlderThanCache() throws Exception {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
- server.enqueue(new MockResponse().setBody("B")
- .addHeader("Last-Modified: " + formatDate(-4, TimeUnit.HOURS)));
- server.play();
-
- URL url = server.getUrl("/");
-
- assertEquals("A", readAscii(url.openConnection()));
- assertEquals("A", readAscii(url.openConnection()));
- }
-
- public void testNonIdentityEncodingAndConditionalCache() throws Exception {
- assertNonIdentityEncodingCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(-1, TimeUnit.HOURS)));
- }
-
- public void testNonIdentityEncodingAndFullCache() throws Exception {
- assertNonIdentityEncodingCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
- }
-
- private void assertNonIdentityEncodingCached(MockResponse response) throws Exception {
- server.enqueue(response
- .setBody(gzip("ABCABCABC".getBytes("UTF-8")))
- .addHeader("Content-Encoding: gzip"));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
- server.play();
- assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
- assertEquals("ABCABCABC", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testExpiresDateBeforeModifiedDate() throws Exception {
- assertConditionallyCached(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Expires: " + formatDate(-2, TimeUnit.HOURS)));
- }
-
- public void testRequestMaxAge() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.HOURS))
- .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES))
- .addHeader("Expires: " + formatDate(1, TimeUnit.HOURS)));
- server.enqueue(new MockResponse().setBody("B"));
-
- server.play();
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
- URLConnection connection = server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "max-age=30");
- assertEquals("B", readAscii(connection));
- }
-
- public void testRequestMinFresh() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
- server.enqueue(new MockResponse().setBody("B"));
-
- server.play();
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
- URLConnection connection = server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "min-fresh=120");
- assertEquals("B", readAscii(connection));
- }
-
- public void testRequestMaxStale() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Cache-Control: max-age=120")
- .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
- server.enqueue(new MockResponse().setBody("B"));
-
- server.play();
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
- URLConnection connection = server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "max-stale=180");
- assertEquals("A", readAscii(connection));
- assertEquals("110 HttpURLConnection \"Response is stale\"",
- connection.getHeaderField("Warning"));
- }
-
- public void testRequestMaxStaleNotHonoredWithMustRevalidate() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Cache-Control: max-age=120, must-revalidate")
- .addHeader("Date: " + formatDate(-4, TimeUnit.MINUTES)));
- server.enqueue(new MockResponse().setBody("B"));
-
- server.play();
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
-
- URLConnection connection = server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "max-stale=180");
- assertEquals("B", readAscii(connection));
- }
-
- public void testRequestOnlyIfCachedWithNoResponseCached() throws IOException {
- // (no responses enqueued)
- server.play();
-
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "only-if-cached");
- assertGatewayTimeout(connection);
- }
-
- public void testRequestOnlyIfCachedWithFullResponseCached() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Cache-Control: max-age=30")
- .addHeader("Date: " + formatDate(0, TimeUnit.MINUTES)));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- URLConnection connection = server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "only-if-cached");
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testRequestOnlyIfCachedWithConditionalResponseCached() throws IOException {
- server.enqueue(new MockResponse().setBody("A")
- .addHeader("Cache-Control: max-age=30")
- .addHeader("Date: " + formatDate(-1, TimeUnit.MINUTES)));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "only-if-cached");
- assertGatewayTimeout(connection);
- }
-
- public void testRequestOnlyIfCachedWithUnhelpfulResponseCached() throws IOException {
- server.enqueue(new MockResponse().setBody("A"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- connection.addRequestProperty("Cache-Control", "only-if-cached");
- assertGatewayTimeout(connection);
- }
-
- public void testRequestCacheControlNoCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- URLConnection connection = url.openConnection();
- connection.setRequestProperty("Cache-Control", "no-cache");
- assertEquals("B", readAscii(connection));
- }
-
- public void testRequestPragmaNoCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-120, TimeUnit.SECONDS))
- .addHeader("Date: " + formatDate(0, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- URLConnection connection = url.openConnection();
- connection.setRequestProperty("Pragma", "no-cache");
- assertEquals("B", readAscii(connection));
- }
-
- public void testClientSuppliedIfModifiedSinceWithCachedResult() throws Exception {
- MockResponse response = new MockResponse()
- .addHeader("ETag: v3")
- .addHeader("Cache-Control: max-age=0");
- String ifModifiedSinceDate = formatDate(-24, TimeUnit.HOURS);
- RecordedRequest request = assertClientSuppliedCondition(
- response, "If-Modified-Since", ifModifiedSinceDate);
- List<String> headers = request.getHeaders();
- assertTrue(headers.contains("If-Modified-Since: " + ifModifiedSinceDate));
- assertFalse(headers.contains("If-None-Match: v3"));
- }
-
- public void testClientSuppliedIfNoneMatchSinceWithCachedResult() throws Exception {
- String lastModifiedDate = formatDate(-3, TimeUnit.MINUTES);
- MockResponse response = new MockResponse()
- .addHeader("Last-Modified: " + lastModifiedDate)
- .addHeader("Date: " + formatDate(-2, TimeUnit.MINUTES))
- .addHeader("Cache-Control: max-age=0");
- RecordedRequest request = assertClientSuppliedCondition(
- response, "If-None-Match", "v1");
- List<String> headers = request.getHeaders();
- assertTrue(headers.contains("If-None-Match: v1"));
- assertFalse(headers.contains("If-Modified-Since: " + lastModifiedDate));
- }
-
- private RecordedRequest assertClientSuppliedCondition(MockResponse seed, String conditionName,
- String conditionValue) throws Exception {
- server.enqueue(seed.setBody("A"));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
-
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.addRequestProperty(conditionName, conditionValue);
- assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
- assertEquals("", readAscii(connection));
-
- server.takeRequest(); // seed
- return server.takeRequest();
- }
-
- public void testSetIfModifiedSince() throws Exception {
- Date since = new Date();
- server.enqueue(new MockResponse().setBody("A"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection = url.openConnection();
- connection.setIfModifiedSince(since.getTime());
- assertEquals("A", readAscii(connection));
- RecordedRequest request = server.takeRequest();
- assertTrue(request.getHeaders().contains("If-Modified-Since: " + formatDate(since)));
- }
-
- public void testClientSuppliedConditionWithoutCachedResult() throws Exception {
- server.enqueue(new MockResponse()
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- HttpURLConnection connection = (HttpURLConnection) server.getUrl("/").openConnection();
- String clientIfModifiedSince = formatDate(-24, TimeUnit.HOURS);
- connection.addRequestProperty("If-Modified-Since", clientIfModifiedSince);
- assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, connection.getResponseCode());
- assertEquals("", readAscii(connection));
- }
-
- public void testAuthorizationRequestHeaderPreventsCaching() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-2, TimeUnit.MINUTES))
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection = url.openConnection();
- connection.addRequestProperty("Authorization", "password");
- assertEquals("A", readAscii(connection));
- assertEquals("B", readAscii(url.openConnection()));
- }
-
- public void testAuthorizationResponseCachedWithSMaxAge() throws Exception {
- assertAuthorizationRequestFullyCached(new MockResponse()
- .addHeader("Cache-Control: s-maxage=60"));
- }
-
- public void testAuthorizationResponseCachedWithPublic() throws Exception {
- assertAuthorizationRequestFullyCached(new MockResponse()
- .addHeader("Cache-Control: public"));
- }
-
- public void testAuthorizationResponseCachedWithMustRevalidate() throws Exception {
- assertAuthorizationRequestFullyCached(new MockResponse()
- .addHeader("Cache-Control: must-revalidate"));
- }
-
- public void assertAuthorizationRequestFullyCached(MockResponse response) throws Exception {
- server.enqueue(response
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection = url.openConnection();
- connection.addRequestProperty("Authorization", "password");
- assertEquals("A", readAscii(connection));
- assertEquals("A", readAscii(url.openConnection()));
- }
-
- public void testContentLocationDoesNotPopulateCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Content-Location: /bar")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/foo").openConnection()));
- assertEquals("B", readAscii(server.getUrl("/bar").openConnection()));
- }
-
- public void testUseCachesFalseDoesNotWriteToCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .setBody("A").setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URLConnection connection = server.getUrl("/").openConnection();
- connection.setUseCaches(false);
- assertEquals("A", readAscii(connection));
- assertEquals("B", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testUseCachesFalseDoesNotReadFromCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .setBody("A").setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- URLConnection connection = server.getUrl("/").openConnection();
- connection.setUseCaches(false);
- assertEquals("B", readAscii(connection));
- }
-
- public void testDefaultUseCachesSetsInitialValueOnly() throws Exception {
- URL url = new URL("http://localhost/");
- URLConnection c1 = url.openConnection();
- URLConnection c2 = url.openConnection();
- assertTrue(c1.getDefaultUseCaches());
- c1.setDefaultUseCaches(false);
- try {
- assertTrue(c1.getUseCaches());
- assertTrue(c2.getUseCaches());
- URLConnection c3 = url.openConnection();
- assertFalse(c3.getUseCaches());
- } finally {
- c1.setDefaultUseCaches(true);
- }
- }
-
- public void testConnectionIsReturnedToPoolAfterConditionalSuccess() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
- assertEquals("A", readAscii(server.getUrl("/a").openConnection()));
- assertEquals("B", readAscii(server.getUrl("/b").openConnection()));
-
- assertEquals(0, server.takeRequest().getSequenceNumber());
- assertEquals(1, server.takeRequest().getSequenceNumber());
- assertEquals(2, server.takeRequest().getSequenceNumber());
- }
-
- public void testStatisticsConditionalCacheMiss() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.enqueue(new MockResponse().setBody("C"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals(1, cache.getRequestCount());
- assertEquals(1, cache.getNetworkCount());
- assertEquals(0, cache.getHitCount());
- assertEquals("B", readAscii(server.getUrl("/").openConnection()));
- assertEquals("C", readAscii(server.getUrl("/").openConnection()));
- assertEquals(3, cache.getRequestCount());
- assertEquals(3, cache.getNetworkCount());
- assertEquals(0, cache.getHitCount());
- }
-
- public void testStatisticsConditionalCacheHit() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals(1, cache.getRequestCount());
- assertEquals(1, cache.getNetworkCount());
- assertEquals(0, cache.getHitCount());
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals(3, cache.getRequestCount());
- assertEquals(3, cache.getNetworkCount());
- assertEquals(2, cache.getHitCount());
- }
-
- public void testStatisticsFullCacheHit() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals(1, cache.getRequestCount());
- assertEquals(1, cache.getNetworkCount());
- assertEquals(0, cache.getHitCount());
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals(3, cache.getRequestCount());
- assertEquals(1, cache.getNetworkCount());
- assertEquals(2, cache.getHitCount());
- }
-
- public void testVaryMatchesChangedRequestHeaderField() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- HttpURLConnection frConnection = (HttpURLConnection) url.openConnection();
- frConnection.addRequestProperty("Accept-Language", "fr-CA");
- assertEquals("A", readAscii(frConnection));
-
- HttpURLConnection enConnection = (HttpURLConnection) url.openConnection();
- enConnection.addRequestProperty("Accept-Language", "en-US");
- assertEquals("B", readAscii(enConnection));
- }
-
- public void testVaryMatchesUnchangedRequestHeaderField() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection1 = url.openConnection();
- connection1.addRequestProperty("Accept-Language", "fr-CA");
- assertEquals("A", readAscii(connection1));
- URLConnection connection2 = url.openConnection();
- connection2.addRequestProperty("Accept-Language", "fr-CA");
- assertEquals("A", readAscii(connection2));
- }
-
- public void testVaryMatchesAbsentRequestHeaderField() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Foo")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testVaryMatchesAddedRequestHeaderField() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Foo")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- URLConnection fooConnection = server.getUrl("/").openConnection();
- fooConnection.addRequestProperty("Foo", "bar");
- assertEquals("B", readAscii(fooConnection));
- }
-
- public void testVaryMatchesRemovedRequestHeaderField() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Foo")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URLConnection fooConnection = server.getUrl("/").openConnection();
- fooConnection.addRequestProperty("Foo", "bar");
- assertEquals("A", readAscii(fooConnection));
- assertEquals("B", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testVaryFieldsAreCaseInsensitive() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: ACCEPT-LANGUAGE")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection1 = url.openConnection();
- connection1.addRequestProperty("Accept-Language", "fr-CA");
- assertEquals("A", readAscii(connection1));
- URLConnection connection2 = url.openConnection();
- connection2.addRequestProperty("accept-language", "fr-CA");
- assertEquals("A", readAscii(connection2));
- }
-
- public void testVaryMultipleFieldsWithMatch() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language, Accept-Charset")
- .addHeader("Vary: Accept-Encoding")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection1 = url.openConnection();
- connection1.addRequestProperty("Accept-Language", "fr-CA");
- connection1.addRequestProperty("Accept-Charset", "UTF-8");
- connection1.addRequestProperty("Accept-Encoding", "identity");
- assertEquals("A", readAscii(connection1));
- URLConnection connection2 = url.openConnection();
- connection2.addRequestProperty("Accept-Language", "fr-CA");
- connection2.addRequestProperty("Accept-Charset", "UTF-8");
- connection2.addRequestProperty("Accept-Encoding", "identity");
- assertEquals("A", readAscii(connection2));
- }
-
- public void testVaryMultipleFieldsWithNoMatch() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language, Accept-Charset")
- .addHeader("Vary: Accept-Encoding")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection frConnection = url.openConnection();
- frConnection.addRequestProperty("Accept-Language", "fr-CA");
- frConnection.addRequestProperty("Accept-Charset", "UTF-8");
- frConnection.addRequestProperty("Accept-Encoding", "identity");
- assertEquals("A", readAscii(frConnection));
- URLConnection enConnection = url.openConnection();
- enConnection.addRequestProperty("Accept-Language", "en-CA");
- enConnection.addRequestProperty("Accept-Charset", "UTF-8");
- enConnection.addRequestProperty("Accept-Encoding", "identity");
- assertEquals("B", readAscii(enConnection));
- }
-
- public void testVaryMultipleFieldValuesWithMatch() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection1 = url.openConnection();
- connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
- connection1.addRequestProperty("Accept-Language", "en-US");
- assertEquals("A", readAscii(connection1));
-
- URLConnection connection2 = url.openConnection();
- connection2.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
- connection2.addRequestProperty("Accept-Language", "en-US");
- assertEquals("A", readAscii(connection2));
- }
-
- public void testVaryMultipleFieldValuesWithNoMatch() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- URLConnection connection1 = url.openConnection();
- connection1.addRequestProperty("Accept-Language", "fr-CA, fr-FR");
- connection1.addRequestProperty("Accept-Language", "en-US");
- assertEquals("A", readAscii(connection1));
-
- URLConnection connection2 = url.openConnection();
- connection2.addRequestProperty("Accept-Language", "fr-CA");
- connection2.addRequestProperty("Accept-Language", "en-US");
- assertEquals("B", readAscii(connection2));
- }
-
- public void testVaryAsterisk() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: *")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- assertEquals("A", readAscii(server.getUrl("/").openConnection()));
- assertEquals("B", readAscii(server.getUrl("/").openConnection()));
- }
-
- public void testVaryAndHttps() throws Exception {
- TestSSLContext testSSLContext = TestSSLContext.create();
- server.useHttps(testSSLContext.serverContext.getSocketFactory(), false);
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .addHeader("Vary: Accept-Language")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- HttpsURLConnection connection1 = (HttpsURLConnection) url.openConnection();
- connection1.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- connection1.addRequestProperty("Accept-Language", "en-US");
- assertEquals("A", readAscii(connection1));
-
- HttpsURLConnection connection2 = (HttpsURLConnection) url.openConnection();
- connection2.setSSLSocketFactory(testSSLContext.clientContext.getSocketFactory());
- connection2.addRequestProperty("Accept-Language", "en-US");
- assertEquals("A", readAscii(connection2));
- }
-
- public void testDiskWriteFailureCacheDegradation() throws Exception {
- Deque<InvocationHandler> writeHandlers = mockOs.getHandlers("write");
- int i = 0;
- boolean hasMoreScenarios = true;
- while (hasMoreScenarios) {
- mockOs.enqueueNormal("write", i++);
- mockOs.enqueueFault("write");
- exercisePossiblyFaultyCache(false);
- hasMoreScenarios = writeHandlers.isEmpty();
- writeHandlers.clear();
- }
- System.out.println("Exercising the cache performs " + (i - 1) + " writes.");
- }
-
- public void testDiskReadFailureCacheDegradation() throws Exception {
- Deque<InvocationHandler> readHandlers = mockOs.getHandlers("read");
- int i = 0;
- boolean hasMoreScenarios = true;
- while (hasMoreScenarios) {
- mockOs.enqueueNormal("read", i++);
- mockOs.enqueueFault("read");
- exercisePossiblyFaultyCache(true);
- hasMoreScenarios = readHandlers.isEmpty();
- readHandlers.clear();
- }
- System.out.println("Exercising the cache performs " + (i - 1) + " reads.");
- }
-
- public void testCachePlusCookies() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Set-Cookie: a=FIRST; domain=" + server.getCookieDomain() + ";")
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .addHeader("Set-Cookie: a=SECOND; domain=" + server.getCookieDomain() + ";")
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- assertCookies(url, "a=FIRST");
- assertEquals("A", readAscii(url.openConnection()));
- assertCookies(url, "a=SECOND");
- }
-
- public void testGetHeadersReturnsNetworkEndToEndHeaders() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Allow: GET, HEAD")
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .addHeader("Allow: GET, HEAD, PUT")
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URLConnection connection1 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals("GET, HEAD", connection1.getHeaderField("Allow"));
-
- URLConnection connection2 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection2));
- assertEquals("GET, HEAD, PUT", connection2.getHeaderField("Allow"));
- }
-
- public void testGetHeadersReturnsCachedHopByHopHeaders() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Transfer-Encoding: identity")
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .addHeader("Transfer-Encoding: none")
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URLConnection connection1 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals("identity", connection1.getHeaderField("Transfer-Encoding"));
-
- URLConnection connection2 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection2));
- assertEquals("identity", connection2.getHeaderField("Transfer-Encoding"));
- }
-
- public void testGetHeadersDeletesCached100LevelWarnings() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Warning: 199 test danger")
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URLConnection connection1 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals("199 test danger", connection1.getHeaderField("Warning"));
-
- URLConnection connection2 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection2));
- assertEquals(null, connection2.getHeaderField("Warning"));
- }
-
- public void testGetHeadersRetainsCached200LevelWarnings() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Warning: 299 test danger")
- .addHeader("Last-Modified: " + formatDate(-1, TimeUnit.HOURS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.play();
-
- URLConnection connection1 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals("299 test danger", connection1.getHeaderField("Warning"));
-
- URLConnection connection2 = server.getUrl("/").openConnection();
- assertEquals("A", readAscii(connection2));
- assertEquals("299 test danger", connection2.getHeaderField("Warning"));
- }
-
- public void assertCookies(URL url, String... expectedCookies) throws Exception {
- List<String> actualCookies = new ArrayList<String>();
- for (HttpCookie cookie : cookieManager.getCookieStore().get(url.toURI())) {
- actualCookies.add(cookie.toString());
- }
- assertEquals(Arrays.asList(expectedCookies), actualCookies);
- }
-
- public void testCachePlusRange() throws Exception {
- assertNotCached(new MockResponse()
- .setResponseCode(HttpURLConnection.HTTP_PARTIAL)
- .addHeader("Date: " + formatDate(0, TimeUnit.HOURS))
- .addHeader("Content-Range: bytes 100-100/200")
- .addHeader("Cache-Control: max-age=60"));
- }
-
- public void testConditionalHitUpdatesCache() throws Exception {
- server.enqueue(new MockResponse()
- .addHeader("Last-Modified: " + formatDate(0, TimeUnit.SECONDS))
- .addHeader("Cache-Control: max-age=0")
- .setBody("A"));
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=30")
- .addHeader("Allow: GET, HEAD")
- .setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- // cache miss; seed the cache
- HttpURLConnection connection1 = (HttpURLConnection) server.getUrl("/a").openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals(null, connection1.getHeaderField("Allow"));
-
- // conditional cache hit; update the cache
- HttpURLConnection connection2 = (HttpURLConnection) server.getUrl("/a").openConnection();
- assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
- assertEquals("A", readAscii(connection2));
- assertEquals("GET, HEAD", connection2.getHeaderField("Allow"));
-
- // full cache hit
- HttpURLConnection connection3 = (HttpURLConnection) server.getUrl("/a").openConnection();
- assertEquals("A", readAscii(connection3));
- assertEquals("GET, HEAD", connection3.getHeaderField("Allow"));
-
- assertEquals(2, server.getRequestCount());
- }
-
- /**
- * @param delta the offset from the current date to use. Negative
- * values yield dates in the past; positive values yield dates in the
- * future.
- */
- private String formatDate(long delta, TimeUnit timeUnit) {
- return formatDate(new Date(System.currentTimeMillis() + timeUnit.toMillis(delta)));
- }
-
- private String formatDate(Date date) {
- DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
- rfc1123.setTimeZone(TimeZone.getTimeZone("UTC"));
- return rfc1123.format(date);
- }
-
- private void addRequestBodyIfNecessary(String requestMethod, HttpURLConnection invalidate)
- throws IOException {
- if (requestMethod.equals("POST") || requestMethod.equals("PUT")) {
- invalidate.setDoOutput(true);
- OutputStream requestBody = invalidate.getOutputStream();
- requestBody.write('x');
- requestBody.close();
- }
- }
-
- private void assertNotCached(MockResponse response) throws Exception {
- server.enqueue(response.setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- assertEquals("B", readAscii(url.openConnection()));
- }
-
- private void exercisePossiblyFaultyCache(boolean permitReadBodyFailures) throws Exception {
- server.shutdown();
- server = new MockWebServer();
- server.enqueue(new MockResponse()
- .addHeader("Cache-Control: max-age=60")
- .setBody("A"));
- server.enqueue(new MockResponse().setBody("B"));
- server.play();
-
- URL url = server.getUrl("/" + UUID.randomUUID());
- assertEquals("A", readAscii(url.openConnection()));
-
- URLConnection connection = url.openConnection();
- InputStream in = connection.getInputStream();
- try {
- int bodyChar = in.read();
- assertTrue(bodyChar == 'A' || bodyChar == 'B');
- assertEquals(-1, in.read());
- } catch (IOException e) {
- if (!permitReadBodyFailures) {
- throw e;
- }
- }
- }
-
- /**
- * @return the request with the conditional get headers.
- */
- private RecordedRequest assertConditionallyCached(MockResponse response) throws Exception {
- // scenario 1: condition succeeds
- server.enqueue(response.setBody("A").setStatus("HTTP/1.1 200 A-OK"));
- server.enqueue(new MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_MODIFIED));
-
- // scenario 2: condition fails
- server.enqueue(response.setBody("B").setStatus("HTTP/1.1 200 B-OK"));
- server.enqueue(new MockResponse().setStatus("HTTP/1.1 200 C-OK").setBody("C"));
-
- server.play();
-
- URL valid = server.getUrl("/valid");
- HttpURLConnection connection1 = (HttpURLConnection) valid.openConnection();
- assertEquals("A", readAscii(connection1));
- assertEquals(HttpURLConnection.HTTP_OK, connection1.getResponseCode());
- assertEquals("A-OK", connection1.getResponseMessage());
- HttpURLConnection connection2 = (HttpURLConnection) valid.openConnection();
- assertEquals("A", readAscii(connection2));
- assertEquals(HttpURLConnection.HTTP_OK, connection2.getResponseCode());
- assertEquals("A-OK", connection2.getResponseMessage());
-
- URL invalid = server.getUrl("/invalid");
- HttpURLConnection connection3 = (HttpURLConnection) invalid.openConnection();
- assertEquals("B", readAscii(connection3));
- assertEquals(HttpURLConnection.HTTP_OK, connection3.getResponseCode());
- assertEquals("B-OK", connection3.getResponseMessage());
- HttpURLConnection connection4 = (HttpURLConnection) invalid.openConnection();
- assertEquals("C", readAscii(connection4));
- assertEquals(HttpURLConnection.HTTP_OK, connection4.getResponseCode());
- assertEquals("C-OK", connection4.getResponseMessage());
-
- server.takeRequest(); // regular get
- return server.takeRequest(); // conditional get
- }
-
- private void assertFullyCached(MockResponse response) throws Exception {
- server.enqueue(response.setBody("A"));
- server.enqueue(response.setBody("B"));
- server.play();
-
- URL url = server.getUrl("/");
- assertEquals("A", readAscii(url.openConnection()));
- assertEquals("A", readAscii(url.openConnection()));
- }
-
- /**
- * Shortens the body of {@code response} but not the corresponding headers.
- * Only useful to test how clients respond to the premature conclusion of
- * the HTTP body.
- */
- private MockResponse truncateViolently(MockResponse response, int numBytesToKeep) {
- response.setSocketPolicy(DISCONNECT_AT_END);
- List<String> headers = new ArrayList<String>(response.getHeaders());
- response.setBody(Arrays.copyOfRange(response.getBody(), 0, numBytesToKeep));
- response.getHeaders().clear();
- response.getHeaders().addAll(headers);
- return response;
- }
-
- /**
- * Reads {@code count} characters from the stream. If the stream is
- * exhausted before {@code count} characters can be read, the remaining
- * characters are returned and the stream is closed.
- */
- private String readAscii(URLConnection connection, int count) throws IOException {
- HttpURLConnection httpConnection = (HttpURLConnection) connection;
- InputStream in = httpConnection.getResponseCode() < HttpURLConnection.HTTP_BAD_REQUEST
- ? connection.getInputStream()
- : httpConnection.getErrorStream();
- StringBuilder result = new StringBuilder();
- for (int i = 0; i < count; i++) {
- int value = in.read();
- if (value == -1) {
- in.close();
- break;
- }
- result.append((char) value);
- }
- return result.toString();
- }
-
- private String readAscii(URLConnection connection) throws IOException {
- return readAscii(connection, Integer.MAX_VALUE);
- }
-
- private void reliableSkip(InputStream in, int length) throws IOException {
- while (length > 0) {
- length -= in.skip(length);
- }
- }
-
- private void assertGatewayTimeout(HttpURLConnection connection) throws IOException {
- try {
- connection.getInputStream();
- fail();
- } catch (FileNotFoundException expected) {
- }
- assertEquals(504, connection.getResponseCode());
- assertEquals(-1, connection.getErrorStream().read());
- }
-
- enum TransferKind {
- CHUNKED() {
- @Override void setBody(MockResponse response, byte[] content, int chunkSize)
- throws IOException {
- response.setChunkedBody(content, chunkSize);
- }
- },
- FIXED_LENGTH() {
- @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
- response.setBody(content);
- }
- },
- END_OF_STREAM() {
- @Override void setBody(MockResponse response, byte[] content, int chunkSize) {
- response.setBody(content);
- response.setSocketPolicy(DISCONNECT_AT_END);
- for (Iterator<String> h = response.getHeaders().iterator(); h.hasNext(); ) {
- if (h.next().startsWith("Content-Length:")) {
- h.remove();
- break;
- }
- }
- }
- };
-
- abstract void setBody(MockResponse response, byte[] content, int chunkSize)
- throws IOException;
-
- void setBody(MockResponse response, String content, int chunkSize) throws IOException {
- setBody(response, content.getBytes("UTF-8"), chunkSize);
- }
- }
-
- private <T> List<T> toListOrNull(T[] arrayOrNull) {
- return arrayOrNull != null ? Arrays.asList(arrayOrNull) : null;
- }
-
- /**
- * Returns a gzipped copy of {@code bytes}.
- */
- public byte[] gzip(byte[] bytes) throws IOException {
- ByteArrayOutputStream bytesOut = new ByteArrayOutputStream();
- OutputStream gzippedOut = new GZIPOutputStream(bytesOut);
- gzippedOut.write(bytes);
- gzippedOut.close();
- return bytesOut.toByteArray();
- }
-
- private class InsecureResponseCache extends ResponseCache {
- @Override public CacheRequest put(URI uri, URLConnection connection) throws IOException {
- return cache.put(uri, connection);
- }
-
- @Override public CacheResponse get(URI uri, String requestMethod,
- Map<String, List<String>> requestHeaders) throws IOException {
- final CacheResponse response = cache.get(uri, requestMethod, requestHeaders);
- if (response instanceof SecureCacheResponse) {
- return new CacheResponse() {
- @Override public InputStream getBody() throws IOException {
- return response.getBody();
- }
- @Override public Map<String, List<String>> getHeaders() throws IOException {
- return response.getHeaders();
- }
- };
- }
- return response;
- }
- }
-}
diff --git a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java b/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
deleted file mode 100644
index d7ba441..0000000
--- a/luni/src/test/java/libcore/net/http/ParsedHeadersTest.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
-* 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 libcore.net.http;
-
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import junit.framework.TestCase;
-
-public final class ParsedHeadersTest extends TestCase {
-
- private URI uri;
-
- @Override protected void setUp() throws Exception {
- super.setUp();
- uri = new URI("http", "localhost", "/");
- }
-
- public void testUpperCaseHttpHeaders() {
- RawHeaders headers = new RawHeaders();
- headers.add("CACHE-CONTROL", "no-store");
- headers.add("DATE", "Thu, 01 Jan 1970 00:00:01 UTC");
- headers.add("EXPIRES", "Thu, 01 Jan 1970 00:00:02 UTC");
- headers.add("LAST-MODIFIED", "Thu, 01 Jan 1970 00:00:03 UTC");
- headers.add("ETAG", "v1");
- headers.add("PRAGMA", "no-cache");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoStore());
- assertEquals(new Date(1000), parsedHeaders.getServedDate());
- assertEquals(new Date(2000), parsedHeaders.getExpires());
- assertEquals(new Date(3000), parsedHeaders.getLastModified());
- assertEquals("v1", parsedHeaders.getEtag());
- assertTrue(parsedHeaders.isNoCache());
- }
-
- public void testCommaSeparatedCacheControlHeaders() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "no-store, max-age=60, public");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoStore());
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- assertTrue(parsedHeaders.isPublic());
- }
-
- public void testQuotedFieldName() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "private=\"Set-Cookie\", no-store");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoStore());
- }
-
- public void testUnquotedValue() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "private=Set-Cookie, no-store");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoStore());
- }
-
- public void testQuotedValue() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "private=\" a, no-cache, c \", no-store");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoStore());
- assertFalse(parsedHeaders.isNoCache());
- }
-
- public void testDanglingQuote() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "private=\"a, no-cache, c");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertFalse(parsedHeaders.isNoCache());
- }
-
- public void testTrailingComma() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "public,");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isPublic());
- }
-
- public void testTrailingEquals() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "private=");
- new ResponseHeaders(uri, headers);
- }
-
- public void testSpaceBeforeEquals() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "max-age =60");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testSpaceAfterEqualsWithQuotes() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "max-age= \"60\"");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testSpaceAfterEqualsWithoutQuotes() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "max-age= 60");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testCacheControlRequestDirectivesAreCaseInsensitive() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "NO-CACHE");
- headers.add("Cache-Control", "MAX-AGE=60");
- headers.add("Cache-Control", "MAX-STALE=70");
- headers.add("Cache-Control", "MIN-FRESH=80");
- headers.add("Cache-Control", "ONLY-IF-CACHED");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoCache());
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- assertEquals(70, parsedHeaders.getMaxStaleSeconds());
- assertEquals(80, parsedHeaders.getMinFreshSeconds());
- assertTrue(parsedHeaders.isOnlyIfCached());
- }
-
- public void testCacheControlResponseDirectivesAreCaseInsensitive() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "NO-CACHE");
- headers.add("Cache-Control", "NO-STORE");
- headers.add("Cache-Control", "MAX-AGE=60");
- headers.add("Cache-Control", "S-MAXAGE=70");
- headers.add("Cache-Control", "PUBLIC");
- headers.add("Cache-Control", "MUST-REVALIDATE");
- ResponseHeaders parsedHeaders = new ResponseHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoCache());
- assertTrue(parsedHeaders.isNoStore());
- assertEquals(60, parsedHeaders.getMaxAgeSeconds());
- assertEquals(70, parsedHeaders.getSMaxAgeSeconds());
- assertTrue(parsedHeaders.isPublic());
- assertTrue(parsedHeaders.isMustRevalidate());
- }
-
- public void testPragmaDirectivesAreCaseInsensitive() {
- RawHeaders headers = new RawHeaders();
- headers.add("Pragma", "NO-CACHE");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertTrue(parsedHeaders.isNoCache());
- }
-
- public void testMissingInteger() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "max-age");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(-1, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testInvalidInteger() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "MAX-AGE=pi");
- RequestHeaders requestHeaders = new RequestHeaders(uri, headers);
- assertEquals(-1, requestHeaders.getMaxAgeSeconds());
- }
-
- public void testVeryLargeInteger() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "MAX-AGE=" + (Integer.MAX_VALUE + 1L));
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(Integer.MAX_VALUE, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testNegativeInteger() {
- RawHeaders headers = new RawHeaders();
- headers.add("Cache-Control", "MAX-AGE=-2");
- RequestHeaders parsedHeaders = new RequestHeaders(uri, headers);
- assertEquals(0, parsedHeaders.getMaxAgeSeconds());
- }
-
- public void testParseChallengesWithCommaInRealm() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "s1 realm=\"ab,cd\", s2 realm=\"ef,gh\"");
- assertEquals(Arrays.asList(new Challenge("s1", "ab,cd"), new Challenge("s2", "ef,gh")),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- public void testParseChallengesWithMultipleHeaders() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "s1 realm=\"abc\"");
- headers.add("WWW-Authenticate", "s2 realm=\"def\"");
- assertEquals(Arrays.asList(new Challenge("s1", "abc"), new Challenge("s2", "def")),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- public void testParseChallengesWithExtraWhitespace() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", " s1 realm=\"a\" , s2 realm=\"b\", ");
- assertEquals(Arrays.asList(new Challenge("s1", "a"), new Challenge("s2", "b")),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- public void testParseChallengesWithMissingRealm() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "Basic");
- assertEquals(Collections.<Challenge>emptyList(),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- public void testParseChallengesWithEmptyRealm() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "Basic realm=\"\"");
- assertEquals(Arrays.asList(new Challenge("Basic", "")),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- public void testParseChallengesWithMissingScheme() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "realm=\"a\"");
- assertEquals(Collections.<Challenge>emptyList(),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-
- // http://code.google.com/p/android/issues/detail?id=11140
- public void testParseChallengesWithManyParameters() {
- RawHeaders headers = new RawHeaders();
- headers.add("WWW-Authenticate", "Digest realm=\"abc\","
- + " qop=\"auth,auth-int\","
- + " nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\","
- + " opaque=\"5ccc069c403ebaf9f0171e9517f40e41\","
- + " Basic realm=\"def\"");
- assertEquals(Arrays.asList(new Challenge("Digest", "abc"), new Challenge("Basic", "def")),
- HeaderParser.parseChallenges(headers, "WWW-Authenticate"));
- }
-}
diff --git a/luni/src/test/java/libcore/net/http/RawHeadersTest.java b/luni/src/test/java/libcore/net/http/RawHeadersTest.java
deleted file mode 100644
index d99e851..0000000
--- a/luni/src/test/java/libcore/net/http/RawHeadersTest.java
+++ /dev/null
@@ -1,54 +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.net.http;
-
-import java.util.Arrays;
-import junit.framework.TestCase;
-
-public class RawHeadersTest extends TestCase {
- // http://code.google.com/p/android/issues/detail?id=6684
- public void test_caseInsensitiveButCasePreserving() {
- RawHeaders h = new RawHeaders();
- h.add("Content-Type", "text/plain");
- // Case-insensitive:
- assertEquals("text/plain", h.get("Content-Type"));
- assertEquals("text/plain", h.get("Content-type"));
- assertEquals("text/plain", h.get("content-type"));
- assertEquals("text/plain", h.get("CONTENT-TYPE"));
- // ...but case-preserving:
- assertEquals("Content-Type", h.toMultimap().keySet().toArray()[0]);
-
- // We differ from the RI in that the Map we return is also case-insensitive.
- // Our behavior seems more consistent. (And code that works on the RI will work on Android.)
- assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-Type"));
- assertEquals(Arrays.asList("text/plain"), h.toMultimap().get("Content-type")); // RI fails this.
- }
-
- // The copy constructor used to be broken for headers with multiple values.
- // http://code.google.com/p/android/issues/detail?id=6722
- public void test_copyConstructor() {
- RawHeaders h1 = new RawHeaders();
- h1.add("key", "value1");
- h1.add("key", "value2");
- RawHeaders h2 = RawHeaders.fromMultimap(h1.toMultimap());
- assertEquals(2, h2.length());
- assertEquals("key", h2.getFieldName(0));
- assertEquals("value1", h2.getValue(0));
- assertEquals("key", h2.getFieldName(1));
- assertEquals("value2", h2.getValue(1));
- }
-}
diff --git a/luni/src/test/java/libcore/util/ZoneInfoDBTest.java b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
new file mode 100644
index 0000000..d5f2b6e
--- /dev/null
+++ b/luni/src/test/java/libcore/util/ZoneInfoDBTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.util;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.RandomAccessFile;
+import java.util.TimeZone;
+
+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";
+
+ // 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);
+ 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);
+ assertEquals(CURRENT_VERSION, data.getVersion());
+ assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
+ }
+
+ // Given no tzdata files we can use, we should fall back to built-in "GMT".
+ public void testNoGoodFile() throws Exception {
+ ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(makeEmptyFile());
+ assertEquals("missing", data.getVersion());
+ assertEquals(1, data.getAvailableIDs().length);
+ assertEquals("GMT", data.getAvailableIDs()[0]);
+ }
+
+ // Given a valid override file, we should find ourselves using that.
+ public void testGoodOverrideFile() throws Exception {
+ RandomAccessFile in = new RandomAccessFile(DEFAULT_FILE, "r");
+ byte[] content = new byte[(int) in.length()];
+ in.readFully(content);
+ content[6] = '9';
+ content[7] = '9';
+ content[8] = '9';
+ content[9] = '9';
+ content[10] = 'z';
+ in.close();
+
+ String goodFile = makeTemporaryFile(content);
+ try {
+ ZoneInfoDB.TzData data = new ZoneInfoDB.TzData(goodFile, DEFAULT_FILE);
+ assertEquals("9999z", data.getVersion());
+ assertEquals(TimeZone.getAvailableIDs().length, data.getAvailableIDs().length);
+ } finally {
+ new File(goodFile).delete();
+ }
+ }
+
+ private static String makeCorruptFile() throws Exception {
+ return makeTemporaryFile("invalid content".getBytes());
+ }
+
+ private static String makeEmptyFile() throws Exception {
+ return makeTemporaryFile(new byte[0]);
+ }
+
+ private static String makeTemporaryFile(byte[] content) throws Exception {
+ File f = File.createTempFile("temp-", ".txt");
+ FileOutputStream fos = new FileOutputStream(f);
+ fos.write(content);
+ fos.close();
+ return f.getPath();
+ }
+}
diff --git a/luni/src/test/java/libcore/xml/PullParserTest.java b/luni/src/test/java/libcore/xml/PullParserTest.java
index 71125aa..c59b358 100644
--- a/luni/src/test/java/libcore/xml/PullParserTest.java
+++ b/luni/src/test/java/libcore/xml/PullParserTest.java
@@ -742,8 +742,42 @@
assertEquals("foo", parser.getName());
}
+ public void testEofInElementSpecRelaxed() throws Exception {
+ assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo (unterminated");
+ }
+
+ public void testEofInAttributeValue() throws Exception {
+ assertParseFailure("<!DOCTYPE foo [<!ATTLIST foo x y \"unterminated");
+ }
+
+ public void testEofInEntityValue() throws Exception {
+ assertParseFailure("<!DOCTYPE foo [<!ENTITY aaa \"unterminated");
+ }
+
+ public void testEofInStartTagAttributeValue() throws Exception {
+ assertParseFailure("<long foo=\"unterminated");
+ }
+
+ public void testEofInReadCharRelaxed() throws Exception {
+ assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo ()"); // EOF in read('>')
+ }
+
+ public void testEofAfterReadCharArrayRelaxed() throws Exception {
+ assertRelaxedParseFailure("<!DOCTYPE foo [<!ELEMENT foo EMPTY"); // EOF in read('>')
+ }
+
private void assertParseFailure(String xml) throws Exception {
XmlPullParser parser = newPullParser();
+ assertParseFailure(xml, parser);
+ }
+
+ private void assertRelaxedParseFailure(String xml) throws Exception {
+ XmlPullParser parser = newPullParser();
+ parser.setFeature("http://xmlpull.org/v1/doc/features.html#relaxed", true);
+ assertParseFailure(xml, parser);
+ }
+
+ private void assertParseFailure(String xml, XmlPullParser parser) throws Exception {
parser.setInput(new StringReader(xml));
try {
while (parser.next() != XmlPullParser.END_DOCUMENT) {
diff --git a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
index 7b39706..f6dec65 100644
--- a/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
+++ b/luni/src/test/java/org/apache/harmony/archive/tests/java/util/jar/JarFileTest.java
@@ -76,6 +76,8 @@
private final String jarName8 = "hyts_signed_sha512digest_sha512withecdsa.jar";
+ private final String authAttrsJar = "hyts_signed_authAttrs.jar";
+
private final String entryName = "foo/bar/A.class";
private final String entryName3 = "coucou/FileAccess.class";
@@ -602,6 +604,9 @@
// SHA-512 digest, SHA512withECDSA signed JAR
checkSignedJar(jarName8);
+
+ // JAR with a signature that has PKCS#7 Authenticated Attributes
+ checkSignedJar(authAttrsJar);
}
private void checkSignedJar(String jarName) throws Exception {
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
index d65dd4b..b1559f5 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
@@ -22,7 +22,6 @@
package org.apache.harmony.crypto.tests.javax.crypto;
-import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -30,7 +29,6 @@
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
-import java.security.spec.DSAParameterSpec;
import java.security.spec.PSSParameterSpec;
import java.util.Arrays;
@@ -44,9 +42,6 @@
import org.apache.harmony.crypto.tests.support.MyMacSpi;
import org.apache.harmony.security.tests.support.SpiEngUtils;
-import org.apache.harmony.xnet.provider.jsse.NativeCryptoTest;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLEngine;
-import org.apache.harmony.xnet.provider.jsse.OpenSSLProvider;
import junit.framework.TestCase;
@@ -891,46 +886,6 @@
}
}
- public void test_getInstance_OpenSSL_ENGINE() throws Exception {
- final String secret = "-HMAC-test1";
- final byte[] testString = "testing123".getBytes();
-
- Provider p = Security.getProvider(OpenSSLProvider.PROVIDER_NAME);
- NativeCryptoTest.loadTestEngine();
- OpenSSLEngine engine = OpenSSLEngine.getInstance(NativeCryptoTest.TEST_ENGINE_ID);
-
- /*
- * The "-HMAC-" prefix is a special prefix recognized by
- * test_openssl_engine.cpp
- */
- SecretKey key1 = engine.getSecretKeyById(secret, "HmacSHA256");
- SecretKey key1dupe = engine.getSecretKeyById(secret, "HmacSHA256");
-
- /* Non-ENGINE-based SecretKey */
- SecretKey key2 = new SecretKeySpec(secret.getBytes(), "HmacSHA256");
-
- /* The one that is ENGINE-based can't be equal to a non-ENGINE one. */
- assertFalse(key1.equals(key2));
- assertEquals(key1, key1dupe);
- assertNull(key1.getFormat());
- assertNull(key1.getEncoded());
- assertEquals("RAW", key2.getFormat());
- assertEquals(Arrays.toString(secret.getBytes()), Arrays.toString(key2.getEncoded()));
-
- Mac mac1 = Mac.getInstance("HmacSHA256", p);
- mac1.init(key1);
- mac1.update(testString);
- byte[] output1 = mac1.doFinal();
- assertEquals(mac1.getMacLength(), output1.length);
-
- Mac mac2 = Mac.getInstance("HmacSHA256", p);
- mac2.init(key2);
- mac2.update(testString);
- byte[] output2 = mac2.doFinal();
-
- assertEquals(Arrays.toString(output2), Arrays.toString(output1));
- }
-
class Mock_Mac extends Mac {
protected Mock_Mac(MacSpi arg0, Provider arg1, String arg2) {
super(arg0, arg1, arg2);
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java
new file mode 100644
index 0000000..28b57fd
--- /dev/null
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/spec/GCMParameterSpecTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.crypto.tests.javax.crypto.spec;
+
+import java.util.Arrays;
+
+import javax.crypto.spec.GCMParameterSpec;
+
+import junit.framework.TestCase;
+
+public class GCMParameterSpecTest extends TestCase {
+ private static final byte[] TEST_IV = new byte[8];
+
+ public void testConstructor_IntByteArray_Success() throws Exception {
+ new GCMParameterSpec(8, TEST_IV);
+ }
+
+ public void testConstructor_IntByteArray_NegativeTLen_Failure() throws Exception {
+ try {
+ new GCMParameterSpec(-1, TEST_IV);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testConstructor_IntByteArray_NullIv_Failure() throws Exception {
+ try {
+ new GCMParameterSpec(8, null);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testConstructor_IntByteArrayWithOffsets_Success() throws Exception {
+ new GCMParameterSpec(8, TEST_IV, 0, TEST_IV.length);
+ }
+
+ public void testConstructor_IntByteArrayWithOffsets_NullIv_Failure() throws Exception {
+ try {
+ new GCMParameterSpec(8, null, 0, TEST_IV.length);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testConstructor_IntByteArrayWithOffsets_NegativeOffset_Failure() throws Exception {
+ try {
+ new GCMParameterSpec(8, TEST_IV, -1, TEST_IV.length);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testConstructor_IntByteArrayWithOffsets_TooLongLength_Failure() throws Exception {
+ try {
+ new GCMParameterSpec(8, TEST_IV, 0, TEST_IV.length + 1);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+ public void testGetIV_Success() throws Exception {
+ GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV);
+
+ byte[] actual = spec.getIV();
+ assertEquals(Arrays.toString(TEST_IV), Arrays.toString(actual));
+
+ // XOR with 0xFF so we're sure we changed the array
+ for (int i = 0; i < actual.length; i++) {
+ actual[i] ^= 0xFF;
+ }
+
+ assertFalse("Changing the IV returned shouldn't change the parameter spec",
+ Arrays.equals(spec.getIV(), actual));
+ assertEquals(Arrays.toString(TEST_IV), Arrays.toString(spec.getIV()));
+ }
+
+ public void testGetIV_Subarray_Success() throws Exception {
+ GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV, 2, 4);
+ assertEquals(Arrays.toString(Arrays.copyOfRange(TEST_IV, 2, 6)),
+ Arrays.toString(spec.getIV()));
+ }
+
+ public void testGetTLen_Success() throws Exception {
+ GCMParameterSpec spec = new GCMParameterSpec(8, TEST_IV);
+ assertEquals(8, spec.getTLen());
+ }
+}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
index 389194a..ee8ecfa 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/Pattern2Test.java
@@ -28,784 +28,6 @@
*/
public class Pattern2Test extends TestCase {
- public void testSimpleMatch() throws PatternSyntaxException {
- Pattern p = Pattern.compile("foo.*");
-
- Matcher m1 = p.matcher("foo123");
- assertTrue(m1.matches());
- assertTrue(m1.find(0));
- assertTrue(m1.lookingAt());
-
- Matcher m2 = p.matcher("fox");
- assertFalse(m2.matches());
- assertFalse(m2.find(0));
- assertFalse(m2.lookingAt());
-
- assertTrue(Pattern.matches("foo.*", "foo123"));
- assertFalse(Pattern.matches("foo.*", "fox"));
-
- assertFalse(Pattern.matches("bar", "foobar"));
-
- assertTrue(Pattern.matches("", ""));
- }
- public void testCursors() {
- Pattern p;
- Matcher m;
-
- try {
- p = Pattern.compile("foo");
-
- m = p.matcher("foobar");
- assertTrue(m.find());
- assertEquals(0, m.start());
- assertEquals(3, m.end());
- assertFalse(m.find());
-
- // Note: also testing reset here
- m.reset();
- assertTrue(m.find());
- assertEquals(0, m.start());
- assertEquals(3, m.end());
- assertFalse(m.find());
-
- m.reset("barfoobar");
- assertTrue(m.find());
- assertEquals(3, m.start());
- assertEquals(6, m.end());
- assertFalse(m.find());
-
- m.reset("barfoo");
- assertTrue(m.find());
- assertEquals(3, m.start());
- assertEquals(6, m.end());
- assertFalse(m.find());
-
- m.reset("foobarfoobarfoo");
- assertTrue(m.find());
- assertEquals(0, m.start());
- assertEquals(3, m.end());
- assertTrue(m.find());
- assertEquals(6, m.start());
- assertEquals(9, m.end());
- assertTrue(m.find());
- assertEquals(12, m.start());
- assertEquals(15, m.end());
- assertFalse(m.find());
- assertTrue(m.find(0));
- assertEquals(0, m.start());
- assertEquals(3, m.end());
- assertTrue(m.find(4));
- assertEquals(6, m.start());
- assertEquals(9, m.end());
- } catch (PatternSyntaxException e) {
- System.out.println(e.getMessage());
- fail();
- }
- }
- public void testGroups() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- p = Pattern.compile("(p[0-9]*)#?(q[0-9]*)");
-
- m = p.matcher("p1#q3p2q42p5p71p63#q888");
- assertTrue(m.find());
- assertEquals(0, m.start());
- assertEquals(5, m.end());
- assertEquals(2, m.groupCount());
- assertEquals(0, m.start(0));
- assertEquals(5, m.end(0));
- assertEquals(0, m.start(1));
- assertEquals(2, m.end(1));
- assertEquals(3, m.start(2));
- assertEquals(5, m.end(2));
- assertEquals("p1#q3", m.group());
- assertEquals("p1#q3", m.group(0));
- assertEquals("p1", m.group(1));
- assertEquals("q3", m.group(2));
-
- assertTrue(m.find());
- assertEquals(5, m.start());
- assertEquals(10, m.end());
- assertEquals(2, m.groupCount());
- assertEquals(10, m.end(0));
- assertEquals(5, m.start(1));
- assertEquals(7, m.end(1));
- assertEquals(7, m.start(2));
- assertEquals(10, m.end(2));
- assertEquals("p2q42", m.group());
- assertEquals("p2q42", m.group(0));
- assertEquals("p2", m.group(1));
- assertEquals("q42", m.group(2));
-
- assertTrue(m.find());
- assertEquals(15, m.start());
- assertEquals(23, m.end());
- assertEquals(2, m.groupCount());
- assertEquals(15, m.start(0));
- assertEquals(23, m.end(0));
- assertEquals(15, m.start(1));
- assertEquals(18, m.end(1));
- assertEquals(19, m.start(2));
- assertEquals(23, m.end(2));
- assertEquals("p63#q888", m.group());
- assertEquals("p63#q888", m.group(0));
- assertEquals("p63", m.group(1));
- assertEquals("q888", m.group(2));
- assertFalse(m.find());
- }
-
- public void testReplace() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- // Note: examples from book,
- // Hitchens, Ron, 2002, "Java NIO", O'Reilly, page 171
- p = Pattern.compile("a*b");
-
- m = p.matcher("aabfooaabfooabfoob");
- assertTrue(m.replaceAll("-").equals("-foo-foo-foo-"));
- assertTrue(m.replaceFirst("-").equals("-fooaabfooabfoob"));
-
- /*
- * p = Pattern.compile ("\\p{Blank}");
- *
- * m = p.matcher ("fee fie foe fum"); assertTrue
- * (m.replaceFirst("-").equals ("fee-fie foe fum")); assertTrue
- * (m.replaceAll("-").equals ("fee-fie-foe-fum"));
- */
-
- p = Pattern.compile("([bB])yte");
-
- m = p.matcher("Byte for byte");
- assertTrue(m.replaceFirst("$1ite").equals("Bite for byte"));
- assertTrue(m.replaceAll("$1ite").equals("Bite for bite"));
-
- p = Pattern.compile("\\d\\d\\d\\d([- ])");
-
- m = p.matcher("card #1234-5678-1234");
- assertTrue(m.replaceFirst("xxxx$1").equals("card #xxxx-5678-1234"));
- assertTrue(m.replaceAll("xxxx$1").equals("card #xxxx-xxxx-1234"));
-
- p = Pattern.compile("(up|left)( *)(right|down)");
-
- m = p.matcher("left right, up down");
- assertTrue(m.replaceFirst("$3$2$1").equals("right left, up down"));
- assertTrue(m.replaceAll("$3$2$1").equals("right left, down up"));
-
- p = Pattern.compile("([CcPp][hl]e[ea]se)");
-
- m = p.matcher("I want cheese. Please.");
- assertTrue(m.replaceFirst("<b> $1 </b>").equals(
- "I want <b> cheese </b>. Please."));
- assertTrue(m.replaceAll("<b> $1 </b>").equals(
- "I want <b> cheese </b>. <b> Please </b>."));
- }
-
- public void testEscapes() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- // Test \\ sequence
- p = Pattern.compile("([a-z]+)\\\\([a-z]+);");
- m = p.matcher("fred\\ginger;abbott\\costello;jekell\\hyde;");
- assertTrue(m.find());
- assertEquals("fred", m.group(1));
- assertEquals("ginger", m.group(2));
- assertTrue(m.find());
- assertEquals("abbott", m.group(1));
- assertEquals("costello", m.group(2));
- assertTrue(m.find());
- assertEquals("jekell", m.group(1));
- assertEquals("hyde", m.group(2));
- assertFalse(m.find());
-
- // Test \n, \t, \r, \f, \e, \a sequences
- p = Pattern.compile("([a-z]+)[\\n\\t\\r\\f\\e\\a]+([a-z]+)");
- m = p.matcher("aa\nbb;cc\u0009\rdd;ee\u000C\u001Bff;gg\n\u0007hh");
- assertTrue(m.find());
- assertEquals("aa", m.group(1));
- assertEquals("bb", m.group(2));
- assertTrue(m.find());
- assertEquals("cc", m.group(1));
- assertEquals("dd", m.group(2));
- assertTrue(m.find());
- assertEquals("ee", m.group(1));
- assertEquals("ff", m.group(2));
- assertTrue(m.find());
- assertEquals("gg", m.group(1));
- assertEquals("hh", m.group(2));
- assertFalse(m.find());
-
- // Test \\u and \\x sequences
-/* p = Pattern.compile("([0-9]+)[\\u0020:\\x21];");
- m = p.matcher("11:;22 ;33-;44!;");
- assertTrue(m.find());
- assertEquals("11", m.group(1));
- assertTrue(m.find());
- assertEquals("22", m.group(1));
- assertTrue(m.find());
- assertEquals("44", m.group(1));
- assertFalse(m.find());
-*/
- // Test invalid unicode sequences
-/* try {
- p = Pattern.compile("\\u");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\u;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\u002");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\u002;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- // Test invalid hex sequences
- try {
- p = Pattern.compile("\\x");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\x;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\xa");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\xa;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-*/
- // Test \0 (octal) sequences (1, 2 and 3 digit)
- p = Pattern.compile("([0-9]+)[\\07\\040\\0160];");
- m = p.matcher("11\u0007;22:;33 ;44p;");
- assertTrue(m.find());
- assertEquals("11", m.group(1));
- assertTrue(m.find());
- assertEquals("33", m.group(1));
- assertTrue(m.find());
- assertEquals("44", m.group(1));
- assertFalse(m.find());
-
- // Test invalid octal sequences
- try {
- p = Pattern.compile("\\08");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- //originally contributed test did not check the result
- //TODO: check what RI does here
-// try {
-// p = Pattern.compile("\\0477");
-// fail("PatternSyntaxException expected");
-// } catch (PatternSyntaxException e) {
-// }
-
- try {
- p = Pattern.compile("\\0");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\0;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
-
- // Test \c (control character) sequence
- p = Pattern.compile("([0-9]+)[\\cA\\cB\\cC\\cD];");
- m = p.matcher("11\u0001;22:;33\u0002;44p;55\u0003;66\u0004;");
- assertTrue(m.find());
- assertEquals("11", m.group(1));
- assertTrue(m.find());
- assertEquals("33", m.group(1));
- assertTrue(m.find());
- assertEquals("55", m.group(1));
- assertTrue(m.find());
- assertEquals("66", m.group(1));
- assertFalse(m.find());
-
- // More thorough control escape test
- // Ensure that each escape matches exactly the corresponding
- // character
- // code and no others (well, from 0-255 at least)
- int i, j;
- for (i = 0; i < 26; i++) {
- p = Pattern.compile("\\c" + Character.toString((char) ('A' + i)));
- int match_char = -1;
- for (j = 0; j < 255; j++) {
- m = p.matcher(Character.toString((char) j));
- if (m.matches()) {
- assertEquals(-1, match_char);
- match_char = j;
- }
- }
- assertTrue(match_char == i + 1);
- }
-
- // Test invalid control escapes
-// BEGIN android-removed
-// ICU doesn't complain about illegal control sequences
-// try {
-// p = Pattern.compile("\\c");
-// fail("PatternSyntaxException expected");
-// } catch (PatternSyntaxException e) {
-// }
-// END android-removed
-
- //originally contributed test did not check the result
- //TODO: check what RI does here
-// try {
-// p = Pattern.compile("\\c;");
-// fail("PatternSyntaxException expected");
-// } catch (PatternSyntaxException e) {
-// }
-//
-// try {
-// p = Pattern.compile("\\ca;");
-// fail("PatternSyntaxException expected");
-// } catch (PatternSyntaxException e) {
-// }
-//
-// try {
-// p = Pattern.compile("\\c4;");
-// fail("PatternSyntaxException expected");
-// } catch (PatternSyntaxException e) {
-// }
- }
- public void testCharacterClasses() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- // Test one character range
- p = Pattern.compile("[p].*[l]");
- m = p.matcher("paul");
- assertTrue(m.matches());
- m = p.matcher("pool");
- assertTrue(m.matches());
- m = p.matcher("pong");
- assertFalse(m.matches());
- m = p.matcher("pl");
- assertTrue(m.matches());
-
- // Test two character range
- p = Pattern.compile("[pm].*[lp]");
- m = p.matcher("prop");
- assertTrue(m.matches());
- m = p.matcher("mall");
- assertTrue(m.matches());
- m = p.matcher("pong");
- assertFalse(m.matches());
- m = p.matcher("pill");
- assertTrue(m.matches());
-
- // Test range including [ and ]
- p = Pattern.compile("[<\\[].*[\\]>]");
- m = p.matcher("<foo>");
- assertTrue(m.matches());
- m = p.matcher("[bar]");
- assertTrue(m.matches());
- m = p.matcher("{foobar]");
- assertFalse(m.matches());
- m = p.matcher("<pill]");
- assertTrue(m.matches());
-
- // Test range using ^
- p = Pattern.compile("[^bc][a-z]+[tr]");
- m = p.matcher("pat");
- assertTrue(m.matches());
- m = p.matcher("liar");
- assertTrue(m.matches());
- m = p.matcher("car");
- assertFalse(m.matches());
- m = p.matcher("gnat");
- assertTrue(m.matches());
-
- // Test character range using -
- p = Pattern.compile("[a-z]_+[a-zA-Z]-+[0-9p-z]");
- m = p.matcher("d__F-8");
- assertTrue(m.matches());
- m = p.matcher("c_a-q");
- assertTrue(m.matches());
- m = p.matcher("a__R-a");
- assertFalse(m.matches());
- m = p.matcher("r_____d-----5");
- assertTrue(m.matches());
-
- // Test range using unicode characters and unicode and hex escapes
- p = Pattern.compile("[\\u1234-\\u2345]_+[a-z]-+[\u0001-\\x11]");
- m = p.matcher("\u2000_q-\u0007");
- assertTrue(m.matches());
- m = p.matcher("\u1234_z-\u0001");
- assertTrue(m.matches());
- m = p.matcher("r_p-q");
- assertFalse(m.matches());
- m = p.matcher("\u2345_____d-----\n");
- assertTrue(m.matches());
-
-// BEGIN android-removed
-// The "---" collides with ICU's "--" operator and is likely to be a user error
-// anyway, so we simply comment this one out.
-// // Test ranges including the "-" character
-// p = Pattern.compile("[\\*-/]_+[---]!+[--AP]");
-// m = p.matcher("-_-!!A");
-// assertTrue(m.matches());
-// m = p.matcher("\u002b_-!!!-");
-// assertTrue(m.matches());
-// m = p.matcher("!_-!@");
-// assertFalse(m.matches());
-// m = p.matcher(",______-!!!!!!!P");
-// assertTrue(m.matches());
-// END android-removed
-
- // Test nested ranges
- p = Pattern.compile("[pm[t]][a-z]+[[r]lp]");
- m = p.matcher("prop");
- assertTrue(m.matches());
- m = p.matcher("tsar");
- assertTrue(m.matches());
- m = p.matcher("pong");
- assertFalse(m.matches());
- m = p.matcher("moor");
- assertTrue(m.matches());
-
- // Test character class intersection with &&
- // TODO: figure out what x&&y or any class with a null intersection
- // set (like [[a-c]&&[d-f]]) might mean. It doesn't mean "match
- // nothing" and doesn't mean "match anything" so I'm stumped.
- p = Pattern.compile("[[a-p]&&[g-z]]+-+[[a-z]&&q]-+[x&&[a-z]]-+");
- m = p.matcher("h--q--x--");
- assertTrue(m.matches());
- m = p.matcher("hog--q-x-");
- assertTrue(m.matches());
- m = p.matcher("ape--q-x-");
- assertFalse(m.matches());
- m = p.matcher("mop--q-x----");
- assertTrue(m.matches());
-
- // Test error cases with &&
-// BEGIN android-removed
-// This is more of a bug, and ICU doesn't have this behavior.
-// p = Pattern.compile("[&&[xyz]]");
-// m = p.matcher("&");
-// // System.out.println(m.matches());
-// m = p.matcher("x");
-// // System.out.println(m.matches());
-// m = p.matcher("y");
-// // System.out.println(m.matches());
-// END android-removed
- p = Pattern.compile("[[xyz]&[axy]]");
- m = p.matcher("x");
- // System.out.println(m.matches());
- m = p.matcher("z");
- // System.out.println(m.matches());
- m = p.matcher("&");
- // System.out.println(m.matches());
- p = Pattern.compile("[abc[123]&&[345]def]");
- m = p.matcher("a");
- // System.out.println(m.matches());
-
-// BEGIN android-removed
-// This is more of a bug, and ICU doesn't have this behavior.
-// p = Pattern.compile("[[xyz]&&]");
-// END android-removed
- p = Pattern.compile("[[abc]&]");
-
- try {
- p = Pattern.compile("[[abc]&&");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- p = Pattern.compile("[[abc]\\&&[xyz]]");
-
- p = Pattern.compile("[[abc]&\\&[xyz]]");
-
- // Test 3-way intersection
- p = Pattern.compile("[[a-p]&&[g-z]&&[d-k]]");
- m = p.matcher("g");
- assertTrue(m.matches());
- m = p.matcher("m");
- assertFalse(m.matches());
-
- // Test nested intersection
- p = Pattern.compile("[[[a-p]&&[g-z]]&&[d-k]]");
- m = p.matcher("g");
- assertTrue(m.matches());
- m = p.matcher("m");
- assertFalse(m.matches());
-
- // Test character class subtraction with && and ^
- p = Pattern.compile("[[a-z]&&[^aeiou]][aeiou][[^xyz]&&[a-z]]");
- m = p.matcher("pop");
- assertTrue(m.matches());
- m = p.matcher("tag");
- assertTrue(m.matches());
- m = p.matcher("eat");
- assertFalse(m.matches());
- m = p.matcher("tax");
- assertFalse(m.matches());
- m = p.matcher("zip");
- assertTrue(m.matches());
-
- // Test . (DOT), with and without DOTALL
- // Note: DOT not allowed in character classes
- p = Pattern.compile(".+/x.z");
- m = p.matcher("!$/xyz");
- assertTrue(m.matches());
- m = p.matcher("%\n\r/x\nz");
- assertFalse(m.matches());
- p = Pattern.compile(".+/x.z", Pattern.DOTALL);
- m = p.matcher("%\n\r/x\nz");
- assertTrue(m.matches());
-
- // Test \d (digit)
- p = Pattern.compile("\\d+[a-z][\\dx]");
- m = p.matcher("42a6");
- assertTrue(m.matches());
- m = p.matcher("21zx");
- assertTrue(m.matches());
- m = p.matcher("ab6");
- assertFalse(m.matches());
- m = p.matcher("56912f9");
- assertTrue(m.matches());
-
- // Test \D (not a digit)
- p = Pattern.compile("\\D+[a-z]-[\\D3]");
- m = p.matcher("za-p");
- assertTrue(m.matches());
- m = p.matcher("%!e-3");
- assertTrue(m.matches());
- m = p.matcher("9a-x");
- assertFalse(m.matches());
- m = p.matcher("\u1234pp\ny-3");
- assertTrue(m.matches());
-
- // Test \s (whitespace)
- p = Pattern.compile("<[a-zA-Z]+\\s+[0-9]+[\\sx][^\\s]>");
- m = p.matcher("<cat \t1\fx>");
- assertTrue(m.matches());
- m = p.matcher("<cat \t1\f >");
- assertFalse(m.matches());
- m = p
- .matcher("xyz <foo\n\r22 5> <pp \t\n\f\r \u000b41x\u1234><pp \nx7\rc> zzz");
- assertTrue(m.find());
- assertTrue(m.find());
- assertFalse(m.find());
-
- // Test \S (not whitespace)
- p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221>");
- m = p.matcher("<f $0**\n** 221>");
- assertTrue(m.matches());
- m = p.matcher("<x 441\t221>");
- assertTrue(m.matches());
- m = p.matcher("<z \t9\ng 221>");
- assertFalse(m.matches());
- m = p.matcher("<z 60\ngg\u1234\f221>");
- assertTrue(m.matches());
- p = Pattern.compile("<[a-z] \\S[0-9][\\S\n]+[^\\S]221[\\S&&[^abc]]>");
- m = p.matcher("<f $0**\n** 221x>");
- assertTrue(m.matches());
- m = p.matcher("<x 441\t221z>");
- assertTrue(m.matches());
- m = p.matcher("<x 441\t221 >");
- assertFalse(m.matches());
- m = p.matcher("<x 441\t221c>");
- assertFalse(m.matches());
- m = p.matcher("<z \t9\ng 221x>");
- assertFalse(m.matches());
- m = p.matcher("<z 60\ngg\u1234\f221\u0001>");
- assertTrue(m.matches());
-
- // Test \w (ascii word)
- p = Pattern.compile("<\\w+\\s[0-9]+;[^\\w]\\w+/[\\w$]+;");
- m = p.matcher("<f1 99;!foo5/a$7;");
- assertTrue(m.matches());
- m = p.matcher("<f$ 99;!foo5/a$7;");
- assertFalse(m.matches());
- m = p
- .matcher("<abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789 99;!foo5/a$7;");
- assertTrue(m.matches());
-
- // Test \W (not an ascii word)
- p = Pattern.compile("<\\W\\w+\\s[0-9]+;[\\W_][^\\W]+\\s[0-9]+;");
- m = p.matcher("<$foo3\n99;_bar\t0;");
- assertTrue(m.matches());
- m = p.matcher("<hh 99;_g 0;");
- assertFalse(m.matches());
- m = p.matcher("<*xx\t00;^zz\f11;");
- assertTrue(m.matches());
-
- // Test x|y pattern
- // TODO
- }
- public void testPOSIXGroups() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- // Test POSIX groups using \p and \P (in the group and not in the group)
- // Groups are Lower, Upper, ASCII, Alpha, Digit, XDigit, Alnum, Punct,
- // Graph, Print, Blank, Space, Cntrl
- // Test \p{Lower}
- /*
- * FIXME: Requires complex range processing
- * p = Pattern.compile("<\\p{Lower}\\d\\P{Lower}:[\\p{Lower}Z]\\s[^\\P{Lower}]>");
- * m = p.matcher("<a4P:g x>"); assertTrue(m.matches()); m =
- * p.matcher("<p4%:Z\tq>"); assertTrue(m.matches()); m =
- * p.matcher("<A6#:e e>"); assertFalse(m.matches());
- */
- p = Pattern.compile("\\p{Lower}+");
- m = p.matcher("abcdefghijklmnopqrstuvwxyz");
- assertTrue(m.matches());
-
- // Invalid uses of \p{Lower}
- try {
- p = Pattern.compile("\\p");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{Lower");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{Lower;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- // Test \p{Upper}
- /*
- * FIXME: Requires complex range processing
- * p = Pattern.compile("<\\p{Upper}\\d\\P{Upper}:[\\p{Upper}z]\\s[^\\P{Upper}]>");
- * m = p.matcher("<A4p:G X>"); assertTrue(m.matches()); m =
- * p.matcher("<P4%:z\tQ>"); assertTrue(m.matches()); m =
- * p.matcher("<a6#:E E>"); assertFalse(m.matches());
- */
- p = Pattern.compile("\\p{Upper}+");
- m = p.matcher("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- assertTrue(m.matches());
-
- // Invalid uses of \p{Upper}
- try {
- p = Pattern.compile("\\p{Upper");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{Upper;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- // Test \p{ASCII}
- /*
- * FIXME: Requires complex range processing p = Pattern.compile("<\\p{ASCII}\\d\\P{ASCII}:[\\p{ASCII}\u1234]\\s[^\\P{ASCII}]>");
- * m = p.matcher("<A4\u0080:G X>"); assertTrue(m.matches()); m =
- * p.matcher("<P4\u00ff:\u1234\t\n>"); assertTrue(m.matches()); m =
- * p.matcher("<\u00846#:E E>"); assertFalse(m.matches())
- */
- int i;
- p = Pattern.compile("\\p{ASCII}");
- for (i = 0; i < 0x80; i++) {
- m = p.matcher(Character.toString((char) i));
- assertTrue(m.matches());
- }
- for (; i < 0xff; i++) {
- m = p.matcher(Character.toString((char) i));
- assertFalse(m.matches());
- }
-
- // Invalid uses of \p{ASCII}
- try {
- p = Pattern.compile("\\p{ASCII");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- try {
- p = Pattern.compile("\\p{ASCII;");
- fail("PatternSyntaxException expected");
- } catch (PatternSyntaxException e) {
- }
-
- // Test \p{Alpha}
- // TODO
-
- // Test \p{Digit}
- // TODO
-
- // Test \p{XDigit}
- // TODO
-
- // Test \p{Alnum}
- // TODO
-
- // Test \p{Punct}
- // TODO
-
- // Test \p{Graph}
- // TODO
-
- // Test \p{Print}
- // TODO
-
- // Test \p{Blank}
- // TODO
-
- // Test \p{Space}
- // TODO
-
- // Test \p{Cntrl}
- // TODO
- }
public void testUnicodeCategories() throws PatternSyntaxException {
// Test Unicode categories using \p and \P
// One letter codes: L, M, N, P, S, Z, C
@@ -906,75 +128,6 @@
}
}
- public void testUnicodeBlocks() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
- int i, j;
-
- // Test Unicode blocks using \p and \P
- // FIXME:
- // Note that LatinExtended-B and ArabicPresentations-B are unrecognized
- // by the reference JDK.
- for (i = 0; i < UBlocks.length; i++) {
- /*
- * p = Pattern.compile("\\p{"+UBlocks[i].name+"}");
- *
- * if (UBlocks[i].low > 0) { m =
- * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
- * assertFalse(m.matches()); } for (j=UBlocks[i].low; j <=
- * UBlocks[i].high; j++) { m =
- * p.matcher(Character.toString((char)j));
- * assertTrue(m.matches()); } if (UBlocks[i].high < 0xFFFF) { m =
- * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
- * assertFalse(m.matches()); }
- *
- * p = Pattern.compile("\\P{"+UBlocks[i].name+"}");
- *
- * if (UBlocks[i].low > 0) { m =
- * p.matcher(Character.toString((char)(UBlocks[i].low-1)));
- * assertTrue(m.matches()); } for (j=UBlocks[i].low; j <
- * UBlocks[i].high; j++) { m =
- * p.matcher(Character.toString((char)j));
- * assertFalse(m.matches()); } if (UBlocks[i].high < 0xFFFF) { m =
- * p.matcher(Character.toString((char)(UBlocks[i].high+1)));
- * assertTrue(m.matches()); }
- */
-
- p = Pattern.compile("\\p{In" + UBlocks[i].name + "}");
-// BEGIN android-changed
-// Added the name of the block under test to the assertion to get more output.
-
- if (UBlocks[i].low > 0) {
- m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
- assertFalse(UBlocks[i].name, m.matches());
- }
- for (j = UBlocks[i].low; j <= UBlocks[i].high; j++) {
- m = p.matcher(Character.toString((char) j));
- assertTrue(UBlocks[i].name, m.matches());
- }
- if (UBlocks[i].high < 0xFFFF) {
- m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
- assertFalse(UBlocks[i].name, m.matches());
- }
-
- p = Pattern.compile("\\P{In" + UBlocks[i].name + "}");
-
- if (UBlocks[i].low > 0) {
- m = p.matcher(Character.toString((char) (UBlocks[i].low - 1)));
- assertTrue(UBlocks[i].name, m.matches());
- }
- for (j = UBlocks[i].low; j < UBlocks[i].high; j++) {
- m = p.matcher(Character.toString((char) j));
- assertFalse(UBlocks[i].name, m.matches());
- }
- if (UBlocks[i].high < 0xFFFF) {
- m = p.matcher(Character.toString((char) (UBlocks[i].high + 1)));
- assertTrue(UBlocks[i].name, m.matches());
- }
-
-// END android-changed
- }
- }
public void testCapturingGroups() throws PatternSyntaxException {
Pattern p;
Matcher m;
@@ -1142,436 +295,4 @@
// Test negative lookbehind using (?<!...)
// TODO
}
- public void testMisc() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
-
- // Test (?>...)
- // TODO
-
- // Test (?onflags-offflags)
- // Valid flags are i,m,d,s,u,x
- // TODO
-
- // Test (?onflags-offflags:...)
- // TODO
-
- // Test \Q, \E
- p = Pattern.compile("[a-z]+;\\Q[a-z]+;\\Q(foo.*);\\E[0-9]+");
- m = p.matcher("abc;[a-z]+;\\Q(foo.*);411");
- assertTrue(m.matches());
- m = p.matcher("abc;def;foo42;555");
- assertFalse(m.matches());
- m = p.matcher("abc;\\Qdef;\\Qfoo99;\\E123");
- assertFalse(m.matches());
-
- p = Pattern.compile("[a-z]+;(foo[0-9]-\\Q(...)\\E);[0-9]+");
- m = p.matcher("abc;foo5-(...);123");
- assertTrue(m.matches());
- assertEquals("foo5-(...)", m.group(1));
- m = p.matcher("abc;foo9-(xxx);789");
- assertFalse(m.matches());
-
- p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q$-\\E]+);[0-9]+");
- m = p.matcher("abc;bar0-def$-;123");
- assertTrue(m.matches());
-
- // FIXME:
- // This should work the same as the pattern above but fails with the
- // the reference JDK
- p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q-$\\E]+);[0-9]+");
- m = p.matcher("abc;bar0-def$-;123");
- // assertTrue(m.matches());
-
- // FIXME:
- // This should work too .. it looks as if just about anything that
- // has more
- // than one character between \Q and \E is broken in the the reference JDK
- p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\Q[0-9]\\E]+);[0-9]+");
- m = p.matcher("abc;bar0-def[99]-]0x[;123");
- // assertTrue(m.matches());
-
- // This is the same as above but with explicit escapes .. and this
- // does work
- // on the the reference JDK
- p = Pattern.compile("[a-z]+;(bar[0-9]-[a-z\\[0\\-9\\]]+);[0-9]+");
- m = p.matcher("abc;bar0-def[99]-]0x[;123");
- assertTrue(m.matches());
-
- // Test #<comment text>
- // TODO
- }
- public void testCompile1() throws PatternSyntaxException {
- Pattern pattern = Pattern
- .compile("[0-9A-Za-z][0-9A-Za-z\\x2e\\x3a\\x2d\\x5f]*");
- String name = "iso-8859-1";
- assertTrue(pattern.matcher(name).matches());
- }
- public void testCompile2() throws PatternSyntaxException {
- String findString = "\\Qimport\\E";
-
- Pattern pattern = Pattern.compile(findString, 0);
- Matcher matcher = pattern.matcher(new String(
- "import a.A;\n\n import b.B;\nclass C {}"));
-
- assertTrue(matcher.find(0));
- }
- public void testCompile3() throws PatternSyntaxException {
- Pattern p;
- Matcher m;
- p = Pattern.compile("a$");
- m = p.matcher("a\n");
- assertTrue(m.find());
- assertEquals("a", m.group());
- assertFalse(m.find());
-
- p = Pattern.compile("(a$)");
- m = p.matcher("a\n");
- assertTrue(m.find());
- assertEquals("a", m.group());
- assertEquals("a", m.group(1));
- assertFalse(m.find());
-
- p = Pattern.compile("^.*$", Pattern.MULTILINE);
-
- m = p.matcher("a\n");
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("a", m.group());
- assertFalse(m.find());
-
- m = p.matcher("a\nb\n");
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("a", m.group());
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("b", m.group());
- assertFalse(m.find());
-
- m = p.matcher("a\nb");
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("a", m.group());
- assertTrue(m.find());
- assertEquals("b", m.group());
- assertFalse(m.find());
-
- m = p.matcher("\naa\r\nbb\rcc\n\n");
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertTrue(m.group().equals(""));
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("aa", m.group());
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("bb", m.group());
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertEquals("cc", m.group());
- assertTrue(m.find());
- // System.out.println("["+m.group()+"]");
- assertTrue(m.group().equals(""));
- assertFalse(m.find());
-
- m = p.matcher("a");
- assertTrue(m.find());
- assertEquals("a", m.group());
- assertFalse(m.find());
-
-// BEGIN android-removed
-// Makes no sense to duplicate this weird behavior
-// m = p.matcher("");
-// // FIXME: This matches the reference behaviour but is
-// // inconsistent with matching "a" - ie. the end of the
-// // target string should match against $ always but this
-// // appears to work with the null string only when not in
-// // multiline mode (see below)
-// assertFalse(m.find());
-// END android-removed
-
- p = Pattern.compile("^.*$");
- m = p.matcher("");
- assertTrue(m.find());
- assertTrue(m.group().equals(""));
- assertFalse(m.find());
- }
- public void testCompile4() throws PatternSyntaxException {
- String findString = "\\Qpublic\\E";
- StringBuffer text = new StringBuffer(" public class Class {\n"
- + " public class Class {");
-
- Pattern pattern = Pattern.compile(findString, 0);
- Matcher matcher = pattern.matcher(text);
-
- boolean found = matcher.find();
- assertTrue(found);
- assertEquals(4, matcher.start());
- if (found) {
- // modify text
- text.delete(0, text.length());
- text.append("Text have been changed.");
- matcher.reset(text);
- }
-
- found = matcher.find();
- assertFalse(found);
- }
- public void testCompile5() throws PatternSyntaxException {
- Pattern p = Pattern.compile("^[0-9]");
- String s[] = p.split("12", -1);
- assertEquals("", s[0]);
- assertEquals("2", s[1]);
- assertEquals(2, s.length);
- }
-
- // public void testCompile6() {
- // String regex = "[\\p{L}[\\p{Mn}[\\p{Pc}[\\p{Nd}[\\p{Nl}[\\p{Sc}]]]]]]+";
- // String regex = "[\\p{L}\\p{Mn}\\p{Pc}\\p{Nd}\\p{Nl}\\p{Sc}]+";
- // try {
- // Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
- // assertTrue(true);
- // } catch (PatternSyntaxException e) {
- // System.out.println(e.getMessage());
- // assertTrue(false);
- // }
- // }
-
- private static class UBInfo {
- public UBInfo(int low, int high, String name) {
- this.name = name;
- this.low = low;
- this.high = high;
- }
-
- public String name;
-
- public int low, high;
- }
-
- // A table representing the unicode categories
- //private static UBInfo[] UCategories = {
- // Lu
- // Ll
- // Lt
- // Lm
- // Lo
- // Mn
- // Mc
- // Me
- // Nd
- // Nl
- // No
- // Pc
- // Pd
- // Ps
- // Pe
- // Pi
- // Pf
- // Po
- // Sm
- // Sc
- // Sk
- // So
- // Zs
- // Zl
- // Zp
- // Cc
- // Cf
- // Cs
- // Co
- // Cn
- //};
-
- // A table representing the unicode character blocks
- private static UBInfo[] UBlocks = {
- /* 0000; 007F; Basic Latin */
- new UBInfo(0x0000, 0x007F, "BasicLatin"), // Character.UnicodeBlock.BASIC_LATIN
- /* 0080; 00FF; Latin-1 Supplement */
- new UBInfo(0x0080, 0x00FF, "Latin-1Supplement"), // Character.UnicodeBlock.LATIN_1_SUPPLEMENT
- /* 0100; 017F; Latin Extended-A */
- new UBInfo(0x0100, 0x017F, "LatinExtended-A"), // Character.UnicodeBlock.LATIN_EXTENDED_A
- /* 0180; 024F; Latin Extended-B */
- // new UBInfo (0x0180,0x024F,"InLatinExtended-B"), //
- // Character.UnicodeBlock.LATIN_EXTENDED_B
- /* 0250; 02AF; IPA Extensions */
- new UBInfo(0x0250, 0x02AF, "IPAExtensions"), // Character.UnicodeBlock.IPA_EXTENSIONS
- /* 02B0; 02FF; Spacing Modifier Letters */
- new UBInfo(0x02B0, 0x02FF, "SpacingModifierLetters"), // Character.UnicodeBlock.SPACING_MODIFIER_LETTERS
- /* 0300; 036F; Combining Diacritical Marks */
- new UBInfo(0x0300, 0x036F, "CombiningDiacriticalMarks"), // Character.UnicodeBlock.COMBINING_DIACRITICAL_MARKS
- /* 0370; 03FF; Greek */
- new UBInfo(0x0370, 0x03FF, "Greek"), // Character.UnicodeBlock.GREEK
- /* 0400; 04FF; Cyrillic */
- new UBInfo(0x0400, 0x04FF, "Cyrillic"), // Character.UnicodeBlock.CYRILLIC
- /* 0530; 058F; Armenian */
- new UBInfo(0x0530, 0x058F, "Armenian"), // Character.UnicodeBlock.ARMENIAN
- /* 0590; 05FF; Hebrew */
- new UBInfo(0x0590, 0x05FF, "Hebrew"), // Character.UnicodeBlock.HEBREW
- /* 0600; 06FF; Arabic */
- new UBInfo(0x0600, 0x06FF, "Arabic"), // Character.UnicodeBlock.ARABIC
- /* 0700; 074F; Syriac */
- new UBInfo(0x0700, 0x074F, "Syriac"), // Character.UnicodeBlock.SYRIAC
- /* 0780; 07BF; Thaana */
- new UBInfo(0x0780, 0x07BF, "Thaana"), // Character.UnicodeBlock.THAANA
- /* 0900; 097F; Devanagari */
- new UBInfo(0x0900, 0x097F, "Devanagari"), // Character.UnicodeBlock.DEVANAGARI
- /* 0980; 09FF; Bengali */
- new UBInfo(0x0980, 0x09FF, "Bengali"), // Character.UnicodeBlock.BENGALI
- /* 0A00; 0A7F; Gurmukhi */
- new UBInfo(0x0A00, 0x0A7F, "Gurmukhi"), // Character.UnicodeBlock.GURMUKHI
- /* 0A80; 0AFF; Gujarati */
- new UBInfo(0x0A80, 0x0AFF, "Gujarati"), // Character.UnicodeBlock.GUJARATI
- /* 0B00; 0B7F; Oriya */
- new UBInfo(0x0B00, 0x0B7F, "Oriya"), // Character.UnicodeBlock.ORIYA
- /* 0B80; 0BFF; Tamil */
- new UBInfo(0x0B80, 0x0BFF, "Tamil"), // Character.UnicodeBlock.TAMIL
- /* 0C00; 0C7F; Telugu */
- new UBInfo(0x0C00, 0x0C7F, "Telugu"), // Character.UnicodeBlock.TELUGU
- /* 0C80; 0CFF; Kannada */
- new UBInfo(0x0C80, 0x0CFF, "Kannada"), // Character.UnicodeBlock.KANNADA
- /* 0D00; 0D7F; Malayalam */
- new UBInfo(0x0D00, 0x0D7F, "Malayalam"), // Character.UnicodeBlock.MALAYALAM
- /* 0D80; 0DFF; Sinhala */
- new UBInfo(0x0D80, 0x0DFF, "Sinhala"), // Character.UnicodeBlock.SINHALA
- /* 0E00; 0E7F; Thai */
- new UBInfo(0x0E00, 0x0E7F, "Thai"), // Character.UnicodeBlock.THAI
- /* 0E80; 0EFF; Lao */
- new UBInfo(0x0E80, 0x0EFF, "Lao"), // Character.UnicodeBlock.LAO
- /* 0F00; 0FFF; Tibetan */
- new UBInfo(0x0F00, 0x0FFF, "Tibetan"), // Character.UnicodeBlock.TIBETAN
- /* 1000; 109F; Myanmar */
- new UBInfo(0x1000, 0x109F, "Myanmar"), // Character.UnicodeBlock.MYANMAR
- /* 10A0; 10FF; Georgian */
- new UBInfo(0x10A0, 0x10FF, "Georgian"), // Character.UnicodeBlock.GEORGIAN
- /* 1100; 11FF; Hangul Jamo */
- new UBInfo(0x1100, 0x11FF, "HangulJamo"), // Character.UnicodeBlock.HANGUL_JAMO
- /* 1200; 137F; Ethiopic */
- new UBInfo(0x1200, 0x137F, "Ethiopic"), // Character.UnicodeBlock.ETHIOPIC
- /* 13A0; 13FF; Cherokee */
- new UBInfo(0x13A0, 0x13FF, "Cherokee"), // Character.UnicodeBlock.CHEROKEE
- /* 1400; 167F; Unified Canadian Aboriginal Syllabics */
- new UBInfo(0x1400, 0x167F, "UnifiedCanadianAboriginalSyllabics"), // Character.UnicodeBlock.UNIFIED_CANADIAN_ABORIGINAL_SYLLABICS
- /* 1680; 169F; Ogham */
- new UBInfo(0x1680, 0x169F, "Ogham"), // Character.UnicodeBlock.OGHAM
- /* 16A0; 16FF; Runic */
- new UBInfo(0x16A0, 0x16FF, "Runic"), // Character.UnicodeBlock.RUNIC
- /* 1780; 17FF; Khmer */
- new UBInfo(0x1780, 0x17FF, "Khmer"), // Character.UnicodeBlock.KHMER
- /* 1800; 18AF; Mongolian */
- new UBInfo(0x1800, 0x18AF, "Mongolian"), // Character.UnicodeBlock.MONGOLIAN
- /* 1E00; 1EFF; Latin Extended Additional */
- new UBInfo(0x1E00, 0x1EFF, "LatinExtendedAdditional"), // Character.UnicodeBlock.LATIN_EXTENDED_ADDITIONAL
- /* 1F00; 1FFF; Greek Extended */
- new UBInfo(0x1F00, 0x1FFF, "GreekExtended"), // Character.UnicodeBlock.GREEK_EXTENDED
- /* 2000; 206F; General Punctuation */
- new UBInfo(0x2000, 0x206F, "GeneralPunctuation"), // Character.UnicodeBlock.GENERAL_PUNCTUATION
- /* 2070; 209F; Superscripts and Subscripts */
- new UBInfo(0x2070, 0x209F, "SuperscriptsandSubscripts"), // Character.UnicodeBlock.SUPERSCRIPTS_AND_SUBSCRIPTS
- /* 20A0; 20CF; Currency Symbols */
- new UBInfo(0x20A0, 0x20CF, "CurrencySymbols"), // Character.UnicodeBlock.CURRENCY_SYMBOLS
- /* 20D0; 20FF; Combining Marks for Symbols */
- new UBInfo(0x20D0, 0x20FF, "CombiningMarksforSymbols"), // Character.UnicodeBlock.COMBINING_MARKS_FOR_SYMBOLS
- /* 2100; 214F; Letterlike Symbols */
- new UBInfo(0x2100, 0x214F, "LetterlikeSymbols"), // Character.UnicodeBlock.LETTERLIKE_SYMBOLS
- /* 2150; 218F; Number Forms */
- new UBInfo(0x2150, 0x218F, "NumberForms"), // Character.UnicodeBlock.NUMBER_FORMS
- /* 2190; 21FF; Arrows */
- new UBInfo(0x2190, 0x21FF, "Arrows"), // Character.UnicodeBlock.ARROWS
- /* 2200; 22FF; Mathematical Operators */
- new UBInfo(0x2200, 0x22FF, "MathematicalOperators"), // Character.UnicodeBlock.MATHEMATICAL_OPERATORS
- /* 2300; 23FF; Miscellaneous Technical */
- new UBInfo(0x2300, 0x23FF, "MiscellaneousTechnical"), // Character.UnicodeBlock.MISCELLANEOUS_TECHNICAL
- /* 2400; 243F; Control Pictures */
- new UBInfo(0x2400, 0x243F, "ControlPictures"), // Character.UnicodeBlock.CONTROL_PICTURES
- /* 2440; 245F; Optical Character Recognition */
- new UBInfo(0x2440, 0x245F, "OpticalCharacterRecognition"), // Character.UnicodeBlock.OPTICAL_CHARACTER_RECOGNITION
- /* 2460; 24FF; Enclosed Alphanumerics */
- new UBInfo(0x2460, 0x24FF, "EnclosedAlphanumerics"), // Character.UnicodeBlock.ENCLOSED_ALPHANUMERICS
- /* 2500; 257F; Box Drawing */
- new UBInfo(0x2500, 0x257F, "BoxDrawing"), // Character.UnicodeBlock.BOX_DRAWING
- /* 2580; 259F; Block Elements */
- new UBInfo(0x2580, 0x259F, "BlockElements"), // Character.UnicodeBlock.BLOCK_ELEMENTS
- /* 25A0; 25FF; Geometric Shapes */
- new UBInfo(0x25A0, 0x25FF, "GeometricShapes"), // Character.UnicodeBlock.GEOMETRIC_SHAPES
- /* 2600; 26FF; Miscellaneous Symbols */
- new UBInfo(0x2600, 0x26FF, "MiscellaneousSymbols"), // Character.UnicodeBlock.MISCELLANEOUS_SYMBOLS
- /* 2700; 27BF; Dingbats */
- new UBInfo(0x2700, 0x27BF, "Dingbats"), // Character.UnicodeBlock.DINGBATS
- /* 2800; 28FF; Braille Patterns */
- new UBInfo(0x2800, 0x28FF, "BraillePatterns"), // Character.UnicodeBlock.BRAILLE_PATTERNS
- /* 2E80; 2EFF; CJK Radicals Supplement */
- new UBInfo(0x2E80, 0x2EFF, "CJKRadicalsSupplement"), // Character.UnicodeBlock.CJK_RADICALS_SUPPLEMENT
- /* 2F00; 2FDF; Kangxi Radicals */
- new UBInfo(0x2F00, 0x2FDF, "KangxiRadicals"), // Character.UnicodeBlock.KANGXI_RADICALS
- /* 2FF0; 2FFF; Ideographic Description Characters */
- new UBInfo(0x2FF0, 0x2FFF, "IdeographicDescriptionCharacters"), // Character.UnicodeBlock.IDEOGRAPHIC_DESCRIPTION_CHARACTERS
- /* 3000; 303F; CJK Symbols and Punctuation */
- new UBInfo(0x3000, 0x303F, "CJKSymbolsandPunctuation"), // Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
- /* 3040; 309F; Hiragana */
- new UBInfo(0x3040, 0x309F, "Hiragana"), // Character.UnicodeBlock.HIRAGANA
- /* 30A0; 30FF; Katakana */
- new UBInfo(0x30A0, 0x30FF, "Katakana"), // Character.UnicodeBlock.KATAKANA
- /* 3100; 312F; Bopomofo */
- new UBInfo(0x3100, 0x312F, "Bopomofo"), // Character.UnicodeBlock.BOPOMOFO
- /* 3130; 318F; Hangul Compatibility Jamo */
- new UBInfo(0x3130, 0x318F, "HangulCompatibilityJamo"), // Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO
- /* 3190; 319F; Kanbun */
- new UBInfo(0x3190, 0x319F, "Kanbun"), // Character.UnicodeBlock.KANBUN
- /* 31A0; 31BF; Bopomofo Extended */
- new UBInfo(0x31A0, 0x31BF, "BopomofoExtended"), // Character.UnicodeBlock.BOPOMOFO_EXTENDED
- /* 3200; 32FF; Enclosed CJK Letters and Months */
- new UBInfo(0x3200, 0x32FF, "EnclosedCJKLettersandMonths"), // Character.UnicodeBlock.ENCLOSED_CJK_LETTERS_AND_MONTHS
- /* 3300; 33FF; CJK Compatibility */
- new UBInfo(0x3300, 0x33FF, "CJKCompatibility"), // Character.UnicodeBlock.CJK_COMPATIBILITY
- /* 3400; 4DB5; CJK Unified Ideographs Extension A */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
- new UBInfo(0x3400, 0x4DBF, "CJKUnifiedIdeographsExtensionA"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
-// END android-changed
- /* 4E00; 9FFF; CJK Unified Ideographs */
- new UBInfo(0x4E00, 0x9FFF, "CJKUnifiedIdeographs"), // Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
- /* A000; A48F; Yi Syllables */
- new UBInfo(0xA000, 0xA48F, "YiSyllables"), // Character.UnicodeBlock.YI_SYLLABLES
- /* A490; A4CF; Yi Radicals */
- new UBInfo(0xA490, 0xA4CF, "YiRadicals"), // Character.UnicodeBlock.YI_RADICALS
- /* AC00; D7A3; Hangul Syllables */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
- new UBInfo(0xAC00, 0xD7AF, "HangulSyllables"), // Character.UnicodeBlock.HANGUL_SYLLABLES
-// END android-changed
- /* D800; DB7F; High Surrogates */
- /* DB80; DBFF; High Private Use Surrogates */
- /* DC00; DFFF; Low Surrogates */
- /* E000; F8FF; Private Use */
- /* F900; FAFF; CJK Compatibility Ideographs */
- new UBInfo(0xF900, 0xFAFF, "CJKCompatibilityIdeographs"), // Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
- /* FB00; FB4F; Alphabetic Presentation Forms */
- new UBInfo(0xFB00, 0xFB4F, "AlphabeticPresentationForms"), // Character.UnicodeBlock.ALPHABETIC_PRESENTATION_FORMS
- /* FB50; FDFF; Arabic Presentation Forms-A */
- new UBInfo(0xFB50, 0xFDFF, "ArabicPresentationForms-A"), // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_A
- /* FE20; FE2F; Combining Half Marks */
- new UBInfo(0xFE20, 0xFE2F, "CombiningHalfMarks"), // Character.UnicodeBlock.COMBINING_HALF_MARKS
- /* FE30; FE4F; CJK Compatibility Forms */
- new UBInfo(0xFE30, 0xFE4F, "CJKCompatibilityForms"), // Character.UnicodeBlock.CJK_COMPATIBILITY_FORMS
- /* FE50; FE6F; Small Form Variants */
- new UBInfo(0xFE50, 0xFE6F, "SmallFormVariants"), // Character.UnicodeBlock.SMALL_FORM_VARIANTS
- /* FE70; FEFE; Arabic Presentation Forms-B */
- // new UBInfo (0xFE70,0xFEFE,"InArabicPresentationForms-B"), //
- // Character.UnicodeBlock.ARABIC_PRESENTATION_FORMS_B
- /* FEFF; FEFF; Specials */
-// BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
-// FEFF is actually still Arabic Presentation Forms B
-// new UBInfo(0xFEFF, 0xFEFF, "Specials"), // Character.UnicodeBlock.SPECIALS
-// END android-changed
- /* FF00; FFEF; Halfwidth and Fullwidth Forms */
- new UBInfo(0xFF00, 0xFFEF, "HalfwidthandFullwidthForms"), // Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
- /* FFF0; FFFD; Specials */
- // BEGIN android-changed
-// Modified this to reflect current Unicode tables (or maybe it was a typo)
- new UBInfo(0xFFF0, 0xFFFF, "Specials") // Character.UnicodeBlock.SPECIALS
-// END android-changed
- };
}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
index d2d3596..0f9e1e6 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternSyntaxExceptionTest.java
@@ -16,70 +16,130 @@
package org.apache.harmony.regex.tests.java.util.regex;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import junit.framework.TestCase;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
public class PatternSyntaxExceptionTest extends TestCase {
+ public void testPatternSyntaxException() {
+ // Normal case
+ PatternSyntaxException e = new PatternSyntaxException("Foo", "Bar", 0);
+ assertEquals("Foo", e.getDescription());
+ assertEquals("Bar", e.getPattern());
+ assertEquals(0, e.getIndex());
- public void testPatternSyntaxException() {
- // Normal case
- PatternSyntaxException e = new PatternSyntaxException("Foo", "Bar", 0);
- assertEquals("Foo", e.getDescription());
- assertEquals("Bar", e.getPattern());
- assertEquals(0, e.getIndex());
+ String s = e.getMessage();
+ assertTrue(s.contains("Foo"));
+ assertTrue(s.contains("Bar"));
+ assertTrue(s.contains("0"));
- String s = e.getMessage();
- assertTrue(s.contains("Foo"));
- assertTrue(s.contains("Bar"));
- assertTrue(s.contains("0"));
+ // No description specified
+ e = new PatternSyntaxException(null, "Bar", 0);
+ assertEquals(null, e.getDescription());
+ assertEquals("Bar", e.getPattern());
+ assertEquals(0, e.getIndex());
- // No description specified
- e = new PatternSyntaxException(null, "Bar", 0);
- assertEquals(null, e.getDescription());
- assertEquals("Bar", e.getPattern());
- assertEquals(0, e.getIndex());
+ s = e.getMessage();
+ assertFalse(s.contains("Foo"));
+ assertTrue(s.contains("Bar"));
+ assertTrue(s.contains("0"));
- s = e.getMessage();
- assertFalse(s.contains("Foo"));
- assertTrue(s.contains("Bar"));
- assertTrue(s.contains("0"));
+ // No pattern specified
+ e = new PatternSyntaxException("Foo", null, 0);
+ assertEquals("Foo", e.getDescription());
+ assertEquals(null, e.getPattern());
+ assertEquals(0, e.getIndex());
- // No pattern specified
- e = new PatternSyntaxException("Foo", null, 0);
- assertEquals("Foo", e.getDescription());
- assertEquals(null, e.getPattern());
- assertEquals(0, e.getIndex());
+ s = e.getMessage();
+ assertTrue(s.contains("Foo"));
+ assertFalse(s.contains("Bar"));
+ assertTrue(s.contains("0"));
- s = e.getMessage();
- assertTrue(s.contains("Foo"));
- assertFalse(s.contains("Bar"));
- assertTrue(s.contains("0"));
+ // Neither description nor pattern specified
+ e = new PatternSyntaxException(null, null, 0);
+ assertEquals(null, e.getDescription());
+ assertEquals(null, e.getPattern());
+ assertEquals(0, e.getIndex());
- // Neither description nor pattern specified
- e = new PatternSyntaxException(null, null, 0);
- assertEquals(null, e.getDescription());
- assertEquals(null, e.getPattern());
- assertEquals(0, e.getIndex());
+ s = e.getMessage();
+ assertFalse(s.contains("Foo"));
+ assertFalse(s.contains("Bar"));
+ assertTrue(s.contains("0"));
- s = e.getMessage();
- assertFalse(s.contains("Foo"));
- assertFalse(s.contains("Bar"));
- assertTrue(s.contains("0"));
+ // No index specified
+ e = new PatternSyntaxException("Foo", "Bar", -1);
+ assertEquals(-1, e.getIndex());
- // No index specified
- e = new PatternSyntaxException("Foo", "Bar", -1);
- assertEquals(-1, e.getIndex());
+ s = e.getMessage();
+ assertFalse(s.contains("^"));
- s = e.getMessage();
- assertFalse(s.contains("^"));
+ // No pattern, but index specified
+ e = new PatternSyntaxException("Foo", null, 0);
+ assertEquals(0, e.getIndex());
- // No pattern, but index specified
- e = new PatternSyntaxException("Foo", null, 0);
- assertEquals(0, e.getIndex());
+ s = e.getMessage();
+ assertFalse(s.contains("^"));
+ }
- s = e.getMessage();
- assertFalse(s.contains("^"));
+ public void testCase() {
+ String regex = "(";
+ try {
+ Pattern.compile(regex);
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ assertEquals(1, e.getIndex());
+ assertEquals(regex, e.getPattern());
}
+ }
+ public void testCase2() {
+ String regex = "[4-";
+ try {
+ Pattern.compile(regex);
+ fail("PatternSyntaxException expected");
+ } catch (PatternSyntaxException e) {
+ assertEquals(3, e.getIndex());
+ assertEquals(regex, e.getPattern());
+ }
+ }
+
+ // Regression test for HARMONY-3787
+ public void test_objectStreamField() {
+ ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(PatternSyntaxException.class);
+ assertNotNull(objectStreamClass.getField("desc"));
+ }
+
+ public void testSerializationCompatibility() throws Exception {
+ PatternSyntaxException object = new PatternSyntaxException("TESTDESC", "TESTREGEX", 3);
+ SerializationTest.verifyGolden(this, object, PATTERNSYNTAXEXCEPTION_COMPARATOR);
+ }
+
+ public void testSerializationSelf() throws Exception {
+ PatternSyntaxException object = new PatternSyntaxException("TESTDESC", "TESTREGEX", 3);
+ SerializationTest.verifySelf(object, PATTERNSYNTAXEXCEPTION_COMPARATOR);
+ }
+
+ private static final SerializableAssert PATTERNSYNTAXEXCEPTION_COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial, Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial, deserialized);
+
+ PatternSyntaxException initPatternSyntaxException = (PatternSyntaxException) initial;
+ PatternSyntaxException dserPatternSyntaxException = (PatternSyntaxException) deserialized;
+
+ // verify fields
+ assertEquals(initPatternSyntaxException.getDescription(),
+ dserPatternSyntaxException.getDescription());
+ assertEquals(initPatternSyntaxException.getPattern(),
+ dserPatternSyntaxException.getPattern());
+ assertEquals(initPatternSyntaxException.getIndex(),
+ dserPatternSyntaxException.getIndex());
+ }
+ };
}
diff --git a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
index a81d294..a4f534b 100644
--- a/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
+++ b/luni/src/test/java/org/apache/harmony/regex/tests/java/util/regex/PatternTest.java
@@ -76,7 +76,7 @@
assertNotSame(p.matcher("a"), p.matcher("a"));
}
- public void testSplitCharSequenceint() {
+ public void testSplitCharSequenceInt() {
// splitting CharSequence which ends with pattern
// bug6193
assertEquals(",,".split(",", 3).length, 3);
@@ -414,7 +414,7 @@
}
}
- public void testCompileStringint() {
+ public void testCompileStringInt() {
/*
* these tests are needed to verify that appropriate exceptions are
* thrown
@@ -455,6 +455,7 @@
/*
* This pattern should compile - HARMONY-2127
+ * icu4c doesn't support canonical equivalence.
*/
// pattern = "x(?c)y";
// Pattern.compile(pattern);
@@ -628,10 +629,28 @@
assertTrue(mat.matches());
}
- public void testBug181() {
+ public void test_bug_181() {
Pattern.compile("[\\t-\\r]");
}
+ // https://code.google.com/p/android/issues/detail?id=40103
+ public void test_bug_40103() {
+ Pattern.compile("(?<!abc {1,100}|def {1,100}|ghi {1,100})jkl");
+
+ // Looks like harmony had a similar "Bug187"...
+ Pattern.compile("|(?idmsux-idmsux)|(?idmsux-idmsux)|[^|\\[-\\0274|\\,-\\\\[^|W\\}\\nq\\x65\\002\\xFE\\05\\06\\00\\x66\\x47i\\,\\xF2\\=\\06\\u0EA4\\x9B\\x3C\\f\\|\\{\\xE5\\05\\r\\u944A\\xCA\\e|\\x19\\04\\x07\\04\\u607B\\023\\0073\\x91Tr\\0150\\x83]]?(?idmsux-idmsux:\\p{Alpha}{7}?)||(?<=[^\\uEC47\\01\\02\\u3421\\a\\f\\a\\013q\\035w\\e])(?<=\\p{Punct}{0,}?)(?=^\\p{Lower})(?!\\b{8,14})(?<![|\\00-\\0146[^|\\04\\01\\04\\060\\f\\u224DO\\x1A\\xC4\\00\\02\\0315\\0351\\u84A8\\xCBt\\xCC\\06|\\0141\\00\\=\\e\\f\\x6B\\0026Tb\\040\\x76xJ&&[\\\\-\\]\\05\\07\\02\\u2DAF\\t\\x9C\\e\\0023\\02\\,X\\e|\\u6058flY\\u954C]]]{5}?)(?<=\\p{Sc}{8}+)[^|\\026-\\u89BA|o\\u6277\\t\\07\\x50&&\\p{Punct}]{8,14}+((?<=^\\p{Punct})|(?idmsux-idmsux)||(?>[\\x3E-\\]])|(?idmsux-idmsux:\\p{Punct})|(?<![\\0111\\0371\\xDF\\u6A49\\07\\u2A4D\\00\\0212\\02Xd-\\xED[^\\a-\\0061|\\0257\\04\\f\\[\\0266\\043\\03\\x2D\\042&&[^\\f-\\]&&\\s]]])|(?>[|\\n\\042\\uB09F\\06\\u0F2B\\uC96D\\x89\\uC166\\xAA|\\04-\\][^|\\a\\|\\rx\\04\\uA770\\n\\02\\t\\052\\056\\0274\\|\\=\\07\\e|\\00-\\x1D&&[^\\005\\uB15B\\uCDAC\\n\\x74\\0103\\0147\\uD91B\\n\\062G\\u9B4B\\077\\}\\0324&&[^\\0302\\,\\0221\\04\\u6D16\\04xy\\uD193\\[\\061\\06\\045\\x0F|\\e\\xBB\\f\\u1B52\\023\\u3AD2\\033\\007\\022\\}\\x66\\uA63FJ-\\0304]]]]{0,0})||(?<![^|\\0154U\\u0877\\03\\fy\\n\\|\\0147\\07-\\=[|q\\u69BE\\0243\\rp\\053\\02\\x33I\\u5E39\\u9C40\\052-\\xBC[|\\0064-\\?|\\uFC0C\\x30\\0060\\x45\\\\\\02\\?p\\xD8\\0155\\07\\0367\\04\\uF07B\\000J[^|\\0051-\\{|\\u9E4E\\u7328\\]\\u6AB8\\06\\x71\\a\\]\\e\\|KN\\u06AA\\0000\\063\\u2523&&[\\005\\0277\\x41U\\034\\}R\\u14C7\\u4767\\x09\\n\\054Ev\\0144\\<\\f\\,Q-\\xE4]]]]]{3}+)|(?>^+)|(?![^|\\|\\nJ\\t\\<\\04E\\\\\\t\\01\\\\\\02\\|\\=\\}\\xF3\\uBEC2\\032K\\014\\uCC5F\\072q\\|\\0153\\xD9\\0322\\uC6C8[^\\t\\0342\\x34\\x91\\06\\{\\xF1\\a\\u1710\\?\\xE7\\uC106\\02pF\\<&&[^|\\]\\064\\u381D\\u50CF\\eO&&[^|\\06\\x2F\\04\\045\\032\\u8536W\\0377\\0017|\\x06\\uE5FA\\05\\xD4\\020\\04c\\xFC\\02H\\x0A\\r]]]]+?)(?idmsux-idmsux)|(?<![|\\r-\\,&&[I\\t\\r\\0201\\xDB\\e&&[^|\\02\\06\\00\\<\\a\\u7952\\064\\051\\073\\x41\\?n\\040\\0053\\031&&[\\x15-\\|]]]]{8,11}?)(?![^|\\<-\\uA74B\\xFA\\u7CD2\\024\\07n\\<\\x6A\\0042\\uE4FF\\r\\u896B\\[\\=\\042Y&&^\\p{ASCII}]++)|(?<![R-\\|&&[\\a\\0120A\\u6145\\<\\050-d[|\\e-\\uA07C|\\016-\\u80D9]]]{1,}+)|(?idmsux-idmsux)|(?idmsux-idmsux)|(?idmsux-idmsux:\\B{6,}?)|(?<=\\D{5,8}?)|(?>[\\{-\\0207|\\06-\\0276\\p{XDigit}])(?idmsux-idmsux:[^|\\x52\\0012\\]u\\xAD\\0051f\\0142\\\\l\\|\\050\\05\\f\\t\\u7B91\\r\\u7763\\{|h\\0104\\a\\f\\0234\\u2D4F&&^\\P{InGreek}]))");
+ }
+
+ public void test_bug_4472() {
+ // HARMONY-4472
+ Pattern.compile("a*.+");
+ }
+
+ public void test_bug_5858() {
+ // HARMONY-5858
+ Pattern.compile("\\u6211", Pattern.LITERAL);
+ }
+
public void testOrphanQuantifiers() {
try {
Pattern.compile("+++++");
@@ -682,13 +701,13 @@
String IPV4_REGEXP_STR = "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$";
String HOSTNAME_REGEXP_STR = "\\w+[\\w\\-\\.]*";
- Pattern URI_REGEXP = Pattern.compile(URI_REGEXP_STR);
- Pattern REL_URI_REGEXP = Pattern.compile(REL_URI_REGEXP_STR);
- Pattern SCHEME_REGEXP = Pattern.compile(SCHEME_REGEXP_STR);
- Pattern IPV4_REGEXP = Pattern.compile(IPV4_REGEXP_STR);
- Pattern IPV6_REGEXP = Pattern.compile(IPV6_REGEXP_STR);
- Pattern IPV6_REGEXP2 = Pattern.compile(IPV6_REGEXP_STR2);
- Pattern HOSTNAME_REGEXP = Pattern.compile(HOSTNAME_REGEXP_STR);
+ Pattern.compile(URI_REGEXP_STR);
+ Pattern.compile(REL_URI_REGEXP_STR);
+ Pattern.compile(SCHEME_REGEXP_STR);
+ Pattern.compile(IPV4_REGEXP_STR);
+ Pattern.compile(IPV6_REGEXP_STR);
+ Pattern.compile(IPV6_REGEXP_STR2);
+ Pattern.compile(HOSTNAME_REGEXP_STR);
}
public void testFindBoundaryCases1() {
@@ -739,16 +758,15 @@
Pattern pat = Pattern.compile(".*");
Matcher mat = pat.matcher("\na\n");
int k = 0;
-
for (; mat.find(); k++) {
assertEquals(res[k], mat.group());
}
+ assertEquals(4, k);
}
public void testBackReferences() {
Pattern pat = Pattern.compile("(\\((\\w*):(.*):(\\2)\\))");
- Matcher mat = pat
- .matcher("(start1: word :start1)(start2: word :start2)");
+ Matcher mat = pat.matcher("(start1: word :start1)(start2: word :start2)");
int k = 1;
for (; mat.find(); k++) {
assertEquals("start" + k, mat.group(2));
@@ -813,7 +831,6 @@
public void testEmptyFamily() {
Pattern.compile("\\p{Lower}");
- String a = "*";
}
public void testNonCaptConstr() {
@@ -886,21 +903,21 @@
}
public void testCorrectReplacementBackreferencedJointSet() {
- Pattern pat = Pattern.compile("ab(a)*\\1");
- pat = Pattern.compile("abc(cd)fg");
- pat = Pattern.compile("aba*cd");
- pat = Pattern.compile("ab(a)*+cd");
- pat = Pattern.compile("ab(a)*?cd");
- pat = Pattern.compile("ab(a)+cd");
- pat = Pattern.compile(".*(.)\\1");
- pat = Pattern.compile("ab((a)|c|d)e");
- pat = Pattern.compile("abc((a(b))cd)");
- pat = Pattern.compile("ab(a)++cd");
- pat = Pattern.compile("ab(a)?(c)d");
- pat = Pattern.compile("ab(a)?+cd");
- pat = Pattern.compile("ab(a)??cd");
- pat = Pattern.compile("ab(a)??cd");
- pat = Pattern.compile("ab(a){1,3}?(c)d");
+ Pattern.compile("ab(a)*\\1");
+ Pattern.compile("abc(cd)fg");
+ Pattern.compile("aba*cd");
+ Pattern.compile("ab(a)*+cd");
+ Pattern.compile("ab(a)*?cd");
+ Pattern.compile("ab(a)+cd");
+ Pattern.compile(".*(.)\\1");
+ Pattern.compile("ab((a)|c|d)e");
+ Pattern.compile("abc((a(b))cd)");
+ Pattern.compile("ab(a)++cd");
+ Pattern.compile("ab(a)?(c)d");
+ Pattern.compile("ab(a)?+cd");
+ Pattern.compile("ab(a)??cd");
+ Pattern.compile("ab(a)??cd");
+ Pattern.compile("ab(a){1,3}?(c)d");
}
public void testCompilePatternWithTerminatorMark() {
@@ -1020,24 +1037,6 @@
assertTrue(mat.matches());
}
- public void testCompileNonCaptGroup() {
- boolean isCompiled = false;
-
- try {
-// BEGIN android-change
-// We don't have canonical equivalence.
- Pattern pat = Pattern.compile("(?:)");
- pat = Pattern.compile("(?:)", Pattern.DOTALL);
- pat = Pattern.compile("(?:)", Pattern.CASE_INSENSITIVE);
- pat = Pattern.compile("(?:)", Pattern.COMMENTS | Pattern.UNIX_LINES);
-// END android-change
- isCompiled = true;
- } catch (PatternSyntaxException e) {
- System.out.println(e);
- }
- assertTrue(isCompiled);
- }
-
public void testEmbeddedFlags() {
String baseString = "(?i)((?s)a)";
String testString = "A";
@@ -1071,15 +1070,7 @@
}
public void testAltWithFlags() {
- boolean isCompiled = false;
-
- try {
- Pattern pat = Pattern.compile("|(?i-xi)|()");
- isCompiled = true;
- } catch (PatternSyntaxException e) {
- System.out.println(e);
- }
- assertTrue(isCompiled);
+ Pattern.compile("|(?i-xi)|()");
}
public void testRestoreFlagsAfterGroup() {
@@ -1146,276 +1137,6 @@
assertNotNull(pattern);
}
- /**
- * s original test was fixed to pass on RI
- */
-
-// BEGIN android-removed
-// We don't have canonical equivalence.
-// public void testCanonEqFlag() {
-//
-// /*
-// * for decompositions see
-// * http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt
-// * http://www.unicode.org/reports/tr15/#Decomposition
-// */
-// String baseString;
-// String testString;
-// Pattern pat;
-// Matcher mat;
-//
-// baseString = "ab(a*)\\1";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// baseString = "a(abcdf)d";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// baseString = "aabcdfd";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// // \u01E0 -> \u0226\u0304 ->\u0041\u0307\u0304
-// // \u00CC -> \u0049\u0300
-//
-// /*
-// * baseString = "\u01E0\u00CCcdb(ac)"; testString =
-// * "\u0226\u0304\u0049\u0300cdbac"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// */
-// baseString = "\u01E0cdb(a\u00CCc)";
-// testString = "\u0041\u0307\u0304cdba\u0049\u0300c";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// baseString = "a\u00CC";
-// testString = "a\u0049\u0300";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// /*
-// * baseString = "\u0226\u0304cdb(ac\u0049\u0300)"; testString =
-// * "\u01E0cdbac\u00CC"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "cdb(?:\u0041\u0307\u0304\u00CC)"; testString =
-// * "cdb\u0226\u0304\u0049\u0300"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "\u01E0[a-c]\u0049\u0300cdb(ac)"; testString =
-// * "\u01E0b\u00CCcdbac"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "\u01E0|\u00CCcdb(ac)"; testString =
-// * "\u0041\u0307\u0304"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "\u00CC?cdb(ac)*(\u01E0)*[a-c]"; testString =
-// * "cdb\u0041\u0307\u0304b"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// */
-// baseString = "a\u0300";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher("a\u00E0a");
-// assertTrue(mat.find());
-//
-// /*
-// * baseString = "\u7B20\uF9F8abc"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher("\uF9F8\uF9F8abc");
-// * assertTrue(mat.matches());
-// *
-// * //\u01F9 -> \u006E\u0300 //\u00C3 -> \u0041\u0303
-// *
-// * baseString = "cdb(?:\u00C3\u006E\u0300)"; testString =
-// * "cdb\u0041\u0303\u01F9"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * //\u014C -> \u004F\u0304 //\u0163 -> \u0074\u0327
-// *
-// * baseString = "cdb(?:\u0163\u004F\u0304)"; testString =
-// * "cdb\u0074\u0327\u014C"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// */
-// // \u00E1->a\u0301
-// // canonical ordering takes place \u0301\u0327 -> \u0327\u0301
-// baseString = "c\u0327\u0301";
-// testString = "c\u0301\u0327";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// /*
-// * Hangul decompositions
-// */
-// // \uD4DB->\u1111\u1171\u11B6
-// // \uD21E->\u1110\u116D\u11B5
-// // \uD264->\u1110\u1170
-// // not Hangul:\u0453->\u0433\u0301
-// baseString = "a\uD4DB\u1111\u1171\u11B6\uD264";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// baseString = "\u0453c\uD4DB";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// baseString = "a\u1110\u116D\u11B5b\uD21Ebc";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-//
-// /*
-// * baseString = "\uD4DB\uD21E\u1110\u1170cdb(ac)"; testString =
-// * "\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac"; pat =
-// * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-// * pat.matcher(testString); assertTrue(mat.matches());
-// */
-// baseString = "\uD4DB\uD264cdb(a\uD21Ec)";
-// testString = "\u1111\u1171\u11B6\u1110\u1170cdba\u1110\u116D\u11B5c";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// baseString = "a\uD4DB";
-// testString = "a\u1111\u1171\u11B6";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// baseString = "a\uD21E";
-// testString = "a\u1110\u116D\u11B5";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// /*
-// * baseString = "\u1111\u1171\u11B6cdb(ac\u1110\u116D\u11B5)";
-// * testString = "\uD4DBcdbac\uD21E"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "cdb(?:\u1111\u1171\u11B6\uD21E)"; testString =
-// * "cdb\uD4DB\u1110\u116D\u11B5"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * baseString = "\uD4DB[a-c]\u1110\u116D\u11B5cdb(ac)"; testString =
-// * "\uD4DBb\uD21Ecdbac"; pat = Pattern.compile(baseString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// */
-// baseString = "\uD4DB|\u00CCcdb(ac)";
-// testString = "\u1111\u1171\u11B6";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// baseString = "\uD4DB|\u00CCcdb(ac)";
-// testString = "\u1111\u1171";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertFalse(mat.matches());
-//
-// baseString = "\u00CC?cdb(ac)*(\uD4DB)*[a-c]";
-// testString = "cdb\u1111\u1171\u11B6b";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-//
-// baseString = "\uD4DB";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher("a\u1111\u1171\u11B6a");
-// assertTrue(mat.find());
-//
-// baseString = "\u1111";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher("bcda\uD4DBr");
-// assertFalse(mat.find());
-// }
-//
-// /**
-// * s original test was fixed to pass on RI
-// */
-//
-// public void testIndexesCanonicalEq() {
-// String baseString;
-// String testString;
-// Pattern pat;
-// Matcher mat;
-//
-// baseString = "\uD4DB";
-// pat = Pattern.compile(baseString, Pattern.CANON_EQ);
-// mat = pat.matcher("bcda\u1111\u1171\u11B6awr");
-// assertTrue(mat.find());
-// assertEquals(mat.start(), 4);
-// assertEquals(mat.end(), 7);
-//
-// /*
-// * baseString = "\uD4DB\u1111\u1171\u11B6"; pat =
-// * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-// * pat.matcher("bcda\u1111\u1171\u11B6\uD4DBawr");
-// * assertTrue(mat.find()); assertEquals(mat.start(), 4);
-// * assertEquals(mat.end(), 8);
-// *
-// * baseString = "\uD4DB\uD21E\u1110\u1170"; testString =
-// * "abcabc\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac"; pat =
-// * Pattern.compile(baseString, Pattern.CANON_EQ); mat =
-// * pat.matcher(testString); assertTrue(mat.find());
-// * assertEquals(mat.start(), 6); assertEquals(mat.end(), 13);
-// */}
-//
-// /**
-// * s original test was fixed to pass on RI
-// */
-//
-// public void testCanonEqFlagWithSupplementaryCharacters() {
-//
-// /*
-// * \u1D1BF->\u1D1BB\u1D16F->\u1D1B9\u1D165\u1D16F in UTF32
-// * \uD834\uDDBF->\uD834\uDDBB\uD834\uDD6F
-// * ->\uD834\uDDB9\uD834\uDD65\uD834\uDD6F in UTF16
-// */
-// String patString = "abc\uD834\uDDBFef";
-// String testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
-// Pattern pat = Pattern.compile(patString, Pattern.CANON_EQ);
-// Matcher mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-// /*
-// * testString = "abc\uD834\uDDBB\uD834\uDD6Fef"; mat =
-// * pat.matcher(testString); assertTrue(mat.matches());
-// *
-// * patString = "abc\uD834\uDDBB\uD834\uDD6Fef"; testString =
-// * "abc\uD834\uDDBFef"; pat = Pattern.compile(patString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// */
-// testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
-// mat = pat.matcher(testString);
-// assertTrue(mat.matches());
-// /*
-// * patString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef"; testString =
-// * "abc\uD834\uDDBFef"; pat = Pattern.compile(patString,
-// * Pattern.CANON_EQ); mat = pat.matcher(testString);
-// * assertTrue(mat.matches());
-// *
-// * testString = "abc\uD834\uDDBB\uD834\uDD6Fef"; mat =
-// * pat.matcher(testString); assertTrue(mat.matches());
-// */
-// /*
-// * testSupplementary characters with no decomposition
-// */
-// /*
-// * patString = "a\uD9A0\uDE8Ebc\uD834\uDDBB\uD834\uDD6Fe\uDE8Ef";
-// * testString = "a\uD9A0\uDE8Ebc\uD834\uDDBFe\uDE8Ef"; pat =
-// * Pattern.compile(patString, Pattern.CANON_EQ); mat =
-// * pat.matcher(testString); assertTrue(mat.matches());
-// */}
-// END android-removed
-
public void testRangesWithSurrogatesSupplementary() {
String patString = "[abc\uD8D2]";
String testString = "\uD8D2";
@@ -1493,6 +1214,7 @@
// might want to duplicate.
// assertFalse(mat.find());
// END android-changed
+
testString = "abcd\uD8D3abc";
mat = pat.matcher(testString);
assertTrue(mat.find());
@@ -1781,4 +1503,341 @@
boolean isPartialMatch = !m.matches() && m.hitEnd();
assertFalse(isPartialMatch);
}
+
+ public void testCommentsInPattern() {
+ Pattern p = Pattern.compile("ab# this is a comment\ncd", Pattern.COMMENTS);
+ assertTrue(p.matcher("abcd").matches());
+ }
+
+ public void testCompileNonCaptGroup() {
+ // icu4c doesn't support CANON_EQ.
+ Pattern.compile("(?:)"/*, Pattern.CANON_EQ*/);
+ Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.DOTALL);
+ Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.CASE_INSENSITIVE);
+ Pattern.compile("(?:)", /*Pattern.CANON_EQ |*/ Pattern.COMMENTS | Pattern.UNIX_LINES);
+ }
+
+ public void testFlagsMethod() {
+ // icu4c doesn't count inline flags that span the entire regex as being global flags.
+ // Android just returns those flags actually passed to Pattern.compile.
+ if (true) {
+ return;
+ }
+
+ String baseString;
+ Pattern pat;
+
+ // These tests are for compatibility with RI only. Logically we have to
+ // return only flags specified during the compilation. For example
+ // pat.flags() == 0 when we compile Pattern pat =
+ // Pattern.compile("(?i)abc(?-i)"); but the whole expression is compiled
+ // in a case insensitive manner. So there is little sense to do calls to
+ // flags() now.
+ baseString = "(?-i)";
+ pat = Pattern.compile(baseString);
+
+ baseString = "(?idmsux)abc(?-i)vg(?-dmu)";
+ pat = Pattern.compile(baseString);
+ assertEquals(pat.flags(), Pattern.DOTALL | Pattern.COMMENTS);
+
+ baseString = "(?idmsux)abc|(?-i)vg|(?-dmu)";
+ pat = Pattern.compile(baseString);
+ assertEquals(pat.flags(), Pattern.DOTALL | Pattern.COMMENTS);
+
+ baseString = "(?is)a((?x)b.)";
+ pat = Pattern.compile(baseString);
+ assertEquals(pat.flags(), Pattern.DOTALL | Pattern.CASE_INSENSITIVE);
+
+ baseString = "(?i)a((?-i))";
+ pat = Pattern.compile(baseString);
+ assertEquals(pat.flags(), Pattern.CASE_INSENSITIVE);
+
+ baseString = "((?i)a)";
+ pat = Pattern.compile(baseString);
+ assertEquals(pat.flags(), 0);
+
+ pat = Pattern.compile("(?is)abc");
+ assertEquals(pat.flags(), Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
+ }
+
+ public void testCanonEqFlag() {
+ // icu4c doesn't support CANON_EQ.
+ if (true) {
+ return;
+ }
+
+ // for decompositions see
+ // http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt
+ // http://www.unicode.org/reports/tr15/#Decomposition
+ String baseString;
+ String testString;
+ Pattern pat;
+ Matcher mat;
+
+ baseString = "ab(a*)\\1";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ baseString = "a(abcdf)d";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ baseString = "aabcdfd";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ // \u01E0 -> \u0226\u0304 ->\u0041\u0307\u0304
+ // \u00CC -> \u0049\u0300
+
+ baseString = "\u01E0\u00CCcdb(ac)";
+ testString = "\u0226\u0304\u0049\u0300cdbac";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u01E0cdb(a\u00CCc)";
+ testString = "\u0041\u0307\u0304cdba\u0049\u0300c";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "a\u00CC";
+ testString = "a\u0049\u0300";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u0226\u0304cdb(ac\u0049\u0300)";
+ testString = "\u01E0cdbac\u00CC";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "cdb(?:\u0041\u0307\u0304\u00CC)";
+ testString = "cdb\u0226\u0304\u0049\u0300";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u01E0[a-c]\u0049\u0300cdb(ac)";
+ testString = "\u01E0b\u00CCcdbac";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u01E0|\u00CCcdb(ac)";
+ testString = "\u0041\u0307\u0304";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u00CC?cdb(ac)*(\u01E0)*[a-c]";
+ testString = "cdb\u0041\u0307\u0304b";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "a\u0300";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("a\u00E0a");
+ assertTrue(mat.find());
+
+ baseString = "\u7B20\uF9F8abc";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("\uF9F8\uF9F8abc");
+ assertTrue(mat.matches());
+
+ // \u01F9 -> \u006E\u0300
+ // \u00C3 -> \u0041\u0303
+
+ baseString = "cdb(?:\u00C3\u006E\u0300)";
+ testString = "cdb\u0041\u0303\u01F9";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ // \u014C -> \u004F\u0304
+ // \u0163 -> \u0074\u0327
+
+ baseString = "cdb(?:\u0163\u004F\u0304)";
+ testString = "cdb\u0074\u0327\u014C";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ // \u00E1->a\u0301
+ // canonical ordering takes place \u0301\u0327 -> \u0327\u0301
+
+ baseString = "c\u0327\u0301";
+ testString = "c\u0301\u0327";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ /*
+ Hangul decompositions
+ */
+ // \uD4DB->\u1111\u1171\u11B6
+ // \uD21E->\u1110\u116D\u11B5
+ // \uD264->\u1110\u1170
+ // not Hangul:\u0453->\u0433\u0301
+ baseString = "a\uD4DB\u1111\u1171\u11B6\uD264";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ baseString = "\u0453c\uD4DB";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ baseString = "a\u1110\u116D\u11B5b\uD21Ebc";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+
+ baseString = "\uD4DB\uD21E\u1110\u1170cdb(ac)";
+ testString = "\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\uD4DB\uD264cdb(a\uD21Ec)";
+ testString = "\u1111\u1171\u11B6\u1110\u1170cdba\u1110\u116D\u11B5c";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "a\uD4DB";
+ testString = "a\u1111\u1171\u11B6";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "a\uD21E";
+ testString = "a\u1110\u116D\u11B5";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\u1111\u1171\u11B6cdb(ac\u1110\u116D\u11B5)";
+ testString = "\uD4DBcdbac\uD21E";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "cdb(?:\u1111\u1171\u11B6\uD21E)";
+ testString = "cdb\uD4DB\u1110\u116D\u11B5";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\uD4DB[a-c]\u1110\u116D\u11B5cdb(ac)";
+ testString = "\uD4DBb\uD21Ecdbac";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\uD4DB|\u00CCcdb(ac)";
+ testString = "\u1111\u1171\u11B6";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\uD4DB|\u00CCcdb(ac)";
+ testString = "\u1111\u1171";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertFalse(mat.matches());
+
+ baseString = "\u00CC?cdb(ac)*(\uD4DB)*[a-c]";
+ testString = "cdb\u1111\u1171\u11B6b";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ baseString = "\uD4DB";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("a\u1111\u1171\u11B6a");
+ assertTrue(mat.find());
+
+ baseString = "\u1111";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("bcda\uD4DBr");
+ assertFalse(mat.find());
+ }
+
+ public void testIndexesCanonicalEq() {
+ // icu4c doesn't support CANON_EQ.
+ if (true) {
+ return;
+ }
+
+ String baseString;
+ String testString;
+ Pattern pat;
+ Matcher mat;
+
+ baseString = "\uD4DB";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("bcda\u1111\u1171\u11B6awr");
+ assertTrue(mat.find());
+ assertEquals(mat.start(), 4);
+ assertEquals(mat.end(), 7);
+
+ baseString = "\uD4DB\u1111\u1171\u11B6";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher("bcda\u1111\u1171\u11B6\uD4DBawr");
+ assertTrue(mat.find());
+ assertEquals(mat.start(), 4);
+ assertEquals(mat.end(), 8);
+
+ baseString = "\uD4DB\uD21E\u1110\u1170";
+ testString = "abcabc\u1111\u1171\u11B6\u1110\u116D\u11B5\uD264cdbac";
+ pat = Pattern.compile(baseString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.find());
+ assertEquals(mat.start(), 6);
+ assertEquals(mat.end(), 13);
+ }
+
+ public void testCanonEqFlagWithSupplementaryCharacters() {
+ // icu4c doesn't support CANON_EQ.
+ if (true) {
+ return;
+ }
+
+ /*
+ \u1D1BF->\u1D1BB\u1D16F->\u1D1B9\u1D165\u1D16F in UTF32
+ \uD834\uDDBF->\uD834\uDDBB\uD834\uDD6F
+ ->\uD834\uDDB9\uD834\uDD65\uD834\uDD6F in UTF16
+ */
+ String patString = "abc\uD834\uDDBFef";
+ String testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+ Pattern pat = Pattern.compile(patString, Pattern.CANON_EQ);
+ Matcher mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ testString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ patString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+ testString = "abc\uD834\uDDBFef";
+ pat = Pattern.compile(patString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ testString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ patString = "abc\uD834\uDDB9\uD834\uDD65\uD834\uDD6Fef";
+ testString = "abc\uD834\uDDBFef";
+ pat = Pattern.compile(patString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ testString = "abc\uD834\uDDBB\uD834\uDD6Fef";
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+
+ // Test supplementary characters with no decomposition
+ patString = "a\uD9A0\uDE8Ebc\uD834\uDDBB\uD834\uDD6Fe\uDE8Ef";
+ testString = "a\uD9A0\uDE8Ebc\uD834\uDDBFe\uDE8Ef";
+ pat = Pattern.compile(patString, Pattern.CANON_EQ);
+ mat = pat.matcher(testString);
+ assertTrue(mat.matches());
+ }
}
diff --git a/luni/src/test/java/tests/api/java/lang/ProcessTest.java b/luni/src/test/java/tests/api/java/lang/ProcessTest.java
index f875dc0..2a8e0bd 100644
--- a/luni/src/test/java/tests/api/java/lang/ProcessTest.java
+++ b/luni/src/test/java/tests/api/java/lang/ProcessTest.java
@@ -17,192 +17,119 @@
package tests.api.java.lang;
-import dalvik.annotation.BrokenTest;
-
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.ArrayList;
public class ProcessTest extends junit.framework.TestCase {
- /**
- * java.lang.Process#getInputStream()
- */
- public void test_getInputStream() {
- try {
- // Test for:
- //Object[] execArgs = Support_Exec.execJava2(
- // new String[] { "tests.support.Support_AvailTest" }, null,
- // true);
- //Process proc = (Process) execArgs[0];
-
- String[] commands = { "sleep", "1"};
- Process proc = Runtime.getRuntime().exec(commands, null, null);
-
- OutputStream os = proc.getOutputStream();
-
- // first number indicates total stream length
- // second number indicates length of data after second space
- // this will allow us to verify length at start, middle, and end
- os.write("10 5 abcde".getBytes());
- os.close();
-
- InputStream is = proc.getInputStream();
- StringBuffer msg = new StringBuffer("");
- while (true) {
- int c = is.read();
- if (c == -1)
- break;
- msg.append((char) c);
- }
- is.close();
- proc.waitFor();
- //Support_Exec.checkStderr(execArgs);
- proc.destroy();
- assertEquals("true", msg.toString(), msg.toString());
- } catch (IOException e) {
- fail("IOException executing avail test: " + e);
- } catch (InterruptedException e) {
- fail("InterruptedException executing avail test: " + e);
- }
+ public void test_55017() throws Exception {
+ ArrayList<Process> children = new ArrayList<Process>();
+ for (int i = 0; i < 256; ++i) {
+ try {
+ children.add(Runtime.getRuntime().exec(new String[] { "/system/bin/does-not-exist" }, null, null));
+ System.gc();
+ } catch (IOException expected) {
+ }
}
+ assertEquals(0, children.size());
- /**
- * java.lang.Process#getOutputStream()
- */
- public void test_getOutputStream() {
- try {
- String[] commands = { "sleep", "1"};
- Process proc = Runtime.getRuntime().exec(commands, null, null);
- OutputStream os = proc.getOutputStream();
- // send data, and check if it is echoed back correctly
- String str1 = "Some data for testing communication between processes\n";
- String str2 = "More data that serves the same purpose.\n";
- String str3 = "Here is some more data.\n";
- os.write(str1.getBytes());
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- os.close();
- InputStream is = proc.getInputStream();
- StringBuffer msg = new StringBuffer("");
- while (true) {
- int c = is.read();
- if (c == -1)
- break;
- msg.append((char) c);
- }
- is.close();
- proc.waitFor();
- //Support_Exec.checkStderr(execArgs);
- proc.destroy();
- String org = str1;
- String recvd = msg.toString();
- // Doesn't pass on RI
- // assertTrue("Data returned did not match data sent. Received: '"
- // + recvd + "' sent: '" + org + "'", recvd.equals(org));
- } catch (IOException e) {
- fail("IOException executing avail test: " + e);
- } catch (InterruptedException e) {
- fail("InterruptedException executing avail test: " + e);
- }
+ boolean onDevice = new File("/system/bin").exists();
+ String[] psCommand = onDevice ? new String[] { "ps" } : new String[] { "ps", "s" };
+ Process ps = Runtime.getRuntime().exec(psCommand, null, null);
+ int zombieCount = 0;
+ for (String line : readAndCloseStream(ps.getInputStream()).split("\n")) {
+ if (line.contains(" Z ") || line.contains(" Z+ ")) {
+ ++zombieCount;
+ }
}
+ assertEquals(0, zombieCount);
+ }
- public void test_exitValue() {
- try {
- String[] commands = { "ls" };
- Process process = Runtime.getRuntime().exec(commands, null, null);
- try {
- Thread.sleep(5000);
- } catch(Exception e) {
-
- }
- assertTrue(process.exitValue() == 0);
-
- String[] commandsSleep = { "sleep", "3" };
- process = Runtime.getRuntime().exec(commandsSleep, null, null);
- process.destroy();
- try {
- Thread.sleep(5000);
- } catch (Exception e) {}
- assertTrue(process.exitValue() != 0);
-
- process = Runtime.getRuntime().exec(commandsSleep, null, null);
- try {
- process.exitValue();
- fail("IllegalThreadStateException was not thrown.");
- } catch(IllegalThreadStateException itse) {
- //expected
- }
- } catch (IOException e) {
- fail("IOException was thrown.");
- }
+ public void test_getOutputStream() throws Exception {
+ String[] commands = { "cat", "-"};
+ Process p = Runtime.getRuntime().exec(commands, null, null);
+ OutputStream os = p.getOutputStream();
+ // send data, and check if it is echoed back correctly
+ String str1 = "Some data for testing communication between processes\n";
+ String str2 = "More data that serves the same purpose.\n";
+ String str3 = "Here is some more data.\n";
+ os.write(str1.getBytes());
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
+ os.write(str2.getBytes());
+ os.write(str3.getBytes());
+ os.close();
- public void test_Constructor() {
- ProcessClass pc = new ProcessClass();
- assertTrue(pc.exitValue() == 0);
+ String received = readAndCloseStream(p.getInputStream());
+ assertEquals(str1 + str2 + str3, received);
+
+ String stderr = readAndCloseStream(p.getErrorStream());
+ assertEquals("", stderr);
+
+ p.waitFor();
+ p.destroy();
+ }
+
+ public void test_getErrorStream() throws Exception {
+ String[] commands = { "cat", "--no-such-option"};
+ Process p = Runtime.getRuntime().exec(commands, null, null);
+
+ p.getOutputStream().close();
+
+ String received = readAndCloseStream(p.getInputStream());
+ assertEquals("", received);
+
+ String stderr = readAndCloseStream(p.getErrorStream());
+ assertTrue(stderr, stderr.contains("unrecognized option") || stderr.contains("invalid option"));
+
+ p.waitFor();
+ p.destroy();
+ }
+
+ private String readAndCloseStream(InputStream is) throws IOException {
+ StringBuffer result = new StringBuffer();
+ while (true) {
+ int c = is.read();
+ if (c == -1) {
+ break;
+ }
+ result.append((char) c);
}
+ is.close();
+ return result.toString();
+ }
- @BrokenTest("Sporadic timeouts in CTS, but not in CoreTestRunner")
- public void test_destroy() {
- String[] commands = { "ls"};
- try {
- Process process = Runtime.getRuntime().exec(commands, null, null);
- process.destroy();
- } catch (IOException e) {
- fail("IOException was thrown.");
- }
+ public void test_exitValue() throws Exception {
+ String[] commands = { "ls" };
+ Process process = Runtime.getRuntime().exec(commands, null, null);
+ process.waitFor();
+ assertEquals(0, process.exitValue());
+
+ String[] commandsSleep = { "sleep", "3000" };
+ process = Runtime.getRuntime().exec(commandsSleep, null, null);
+ process.destroy();
+ process.waitFor(); // destroy is asynchronous.
+ assertTrue(process.exitValue() != 0);
+
+ process = Runtime.getRuntime().exec(new String[] { "sleep", "3000" }, null, null);
+ try {
+ process.exitValue();
+ fail();
+ } catch(IllegalThreadStateException expected) {
}
+ }
- protected void setUp() {
- }
-
- protected void tearDown() {
- }
-
- protected void doneSuite() {
- }
-
- class ProcessClass extends Process {
-
- ProcessClass() {
- super();
- }
-
- @Override
- public void destroy() {
-
- }
-
- @Override
- public int exitValue() {
- // TODO Auto-generated method stub
- return 0;
- }
-
- @Override
- public InputStream getErrorStream() {
- return null;
- }
-
- @Override
- public InputStream getInputStream() {
- return null;
- }
-
- @Override
- public OutputStream getOutputStream() {
- return null;
- }
-
- @Override
- public int waitFor() throws InterruptedException {
- // TODO Auto-generated method stub
- return 0;
- }
-
- }
+ public void test_destroy() throws Exception {
+ String[] commands = { "ls"};
+ Process process = Runtime.getRuntime().exec(commands, null, null);
+ process.destroy();
+ process.destroy();
+ process.destroy();
+ }
}
diff --git a/luni/src/test/java/tests/api/java/math/BigIntegerTest.java b/luni/src/test/java/tests/api/java/math/BigIntegerTest.java
deleted file mode 100644
index 2c2c25b..0000000
--- a/luni/src/test/java/tests/api/java/math/BigIntegerTest.java
+++ /dev/null
@@ -1,1185 +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.math;
-
-import java.math.BigInteger;
-import java.util.Random;
-
-public class BigIntegerTest extends junit.framework.TestCase {
-
- BigInteger minusTwo = new BigInteger("-2", 10);
-
- BigInteger minusOne = new BigInteger("-1", 10);
-
- BigInteger zero = new BigInteger("0", 10);
-
- BigInteger one = new BigInteger("1", 10);
-
- BigInteger two = new BigInteger("2", 10);
-
- BigInteger ten = new BigInteger("10", 10);
-
- BigInteger sixteen = new BigInteger("16", 10);
-
- BigInteger oneThousand = new BigInteger("1000", 10);
-
- BigInteger aZillion = new BigInteger(
- "100000000000000000000000000000000000000000000000000", 10);
-
- BigInteger twoToTheTen = new BigInteger("1024", 10);
-
- BigInteger twoToTheSeventy = two.pow(70);
-
- Random rand = new Random();
-
- BigInteger bi;
-
- BigInteger bi1;
-
- BigInteger bi2;
-
- BigInteger bi3;
-
- BigInteger bi11;
-
- BigInteger bi22;
-
- BigInteger bi33;
-
- BigInteger bi12;
-
- BigInteger bi23;
-
- BigInteger bi13;
-
- BigInteger largePos;
-
- BigInteger smallPos;
-
- BigInteger largeNeg;
-
- BigInteger smallNeg;
-
- BigInteger[][] booleanPairs;
-
- /**
- * java.math.BigInteger#BigInteger(int, java.util.Random)
- */
- public void test_ConstructorILjava_util_Random() {
- // regression test for HARMONY-1047
- try {
- new BigInteger(Integer.MAX_VALUE, (Random)null);
- fail("NegativeArraySizeException expected");
- } catch (NegativeArraySizeException e) {
- // PASSED
- }
-
- bi = new BigInteger(70, rand);
- bi2 = new BigInteger(70, rand);
- assertTrue("Random number is negative", bi.compareTo(zero) >= 0);
- assertTrue("Random number is too big",
- bi.compareTo(twoToTheSeventy) < 0);
- assertTrue(
- "Two random numbers in a row are the same (might not be a bug but it very likely is)",
- !bi.equals(bi2));
- assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
-
- try {
- new BigInteger(-1, (Random)null);
- fail("IllegalArgumentException expected");
- } catch (IllegalArgumentException e) {
- // PASSED
- }
- }
-
- /**
- * java.math.BigInteger#BigInteger(int, int, java.util.Random)
- */
- // BIGNUM returns no Primes smaller than 16 bits.
- public void test_ConstructorIILjava_util_Random() {
- bi = new BigInteger(10, 5, rand);
- bi2 = new BigInteger(10, 5, rand);
- assertTrue("Random number one is negative", bi.compareTo(zero) >= 0);
- assertTrue("Random number one is too big",
- bi.compareTo(twoToTheTen) < 0);
- assertTrue("Random number two is negative", bi2.compareTo(zero) >= 0);
- assertTrue("Random number two is too big",
- bi2.compareTo(twoToTheTen) < 0);
-
- Random rand = new Random();
- BigInteger bi;
- int certainty[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
- Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1 };
- for (int i = 2; i <= 20; i++) {
- for (int c = 0; c < certainty.length; c++) {
- bi = new BigInteger(i, c, rand); // Create BigInteger
- assertTrue("Bit length incorrect", bi.bitLength() == i);
- }
- }
-
- try {
- new BigInteger(1, 80, (Random)null);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- // PASSED
- }
-
- try {
- new BigInteger(-1, (Random)null);
- fail("IllegalArgumentException expected");
- } catch (IllegalArgumentException e) {
- // PASSED
- }
- }
-
- /**
- * java.math.BigInteger#BigInteger(byte[])
- */
- public void test_Constructor$B() {
- byte[] myByteArray;
- myByteArray = new byte[] { (byte) 0x00, (byte) 0xFF, (byte) 0xFE };
- bi = new BigInteger(myByteArray);
- assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
- .setBit(16).subtract(two)));
- myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
- bi = new BigInteger(myByteArray);
- assertTrue("Incorrect value for neg number", bi.equals(minusTwo));
- }
-
- /**
- * java.math.BigInteger#BigInteger(int, byte[])
- */
- public void test_ConstructorI$B() {
- byte[] myByteArray;
- myByteArray = new byte[] { (byte) 0xFF, (byte) 0xFE };
- bi = new BigInteger(1, myByteArray);
- assertTrue("Incorrect value for pos number", bi.equals(BigInteger.ZERO
- .setBit(16).subtract(two)));
- bi = new BigInteger(-1, myByteArray);
- assertTrue("Incorrect value for neg number", bi.equals(BigInteger.ZERO
- .setBit(16).subtract(two).negate()));
- myByteArray = new byte[] { (byte) 0, (byte) 0 };
- bi = new BigInteger(0, myByteArray);
- assertTrue("Incorrect value for zero", bi.equals(zero));
- myByteArray = new byte[] { (byte) 1 };
- try {
- new BigInteger(0, myByteArray);
- fail("Failed to throw NumberFormatException");
- } catch (NumberFormatException e) {
- // correct
- }
- }
-
- /**
- * java.math.BigInteger#BigInteger(java.lang.String)
- */
- public void test_constructor_String_empty() {
- try {
- new BigInteger("");
- fail("Expected NumberFormatException for new BigInteger(\"\")");
- } catch (NumberFormatException e) {
- }
- }
-
- /**
- * java.math.BigInteger#toByteArray()
- */
- public void test_toByteArray() {
- byte[] myByteArray, anotherByteArray;
- myByteArray = new byte[] { 97, 33, 120, 124, 50, 2, 0, 0, 0, 12, 124,
- 42 };
- anotherByteArray = new BigInteger(myByteArray).toByteArray();
- assertTrue("Incorrect byte array returned",
- myByteArray.length == anotherByteArray.length);
- for (int counter = myByteArray.length - 1; counter >= 0; counter--) {
- assertTrue("Incorrect values in returned byte array",
- myByteArray[counter] == anotherByteArray[counter]);
- }
- }
-
-// public void test_SpecialPrimes() {
-// System.out.println("test_SpecialPrimes");
-// final BigInteger TWO = BigInteger.valueOf(2);
-// BigInteger p, q;
-// for (;;) {
-// p = new BigInteger(1024, 23, new Random());
-// q = p.subtract(BigInteger.ONE).divide(TWO);
-// if (q.isProbablePrime(20)) {
-// System.out.println(q);
-// System.out.println(p);
-// break;
-// }
-// System.out.print(".");
-// }
-// fail("isProbablePrime failed for: " + bi);
-// }
-
- /**
- * java.math.BigInteger#isProbablePrime(int)
- */
- public void test_isProbablePrimeI() {
- int fails = 0;
- bi = new BigInteger(20, 20, rand);
- if (!bi.isProbablePrime(17)) {
- fails++;
- }
- bi = new BigInteger("4", 10);
- if (bi.isProbablePrime(17)) {
- fail("isProbablePrime failed for: " + bi);
- }
- bi = BigInteger.valueOf(17L * 13L);
- if (bi.isProbablePrime(17)) {
- fail("isProbablePrime failed for: " + bi);
- }
- for (long a = 2; a < 1000; a++) {
- if (isPrime(a)) {
- assertTrue("false negative on prime number <1000", BigInteger
- .valueOf(a).isProbablePrime(5));
- } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
- System.out.println("isProbablePrime failed for: " + a);
- fails++;
- }
- }
- for (int a = 0; a < 1000; a++) {
- bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
- BigInteger.valueOf(rand.nextInt(1000000)));
- if (bi.isProbablePrime(17)) {
- System.out.println("isProbablePrime failed for: " + bi);
- fails++;
- }
- }
- for (int a = 0; a < 200; a++) {
- bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
- if (bi.isProbablePrime(17)) {
- System.out.println("isProbablePrime failed for: " + bi);
- fails++;
- }
- }
- assertTrue("Too many false positives - may indicate a problem",
- fails <= 1);
-
- //
- // And now some tests on real big integers:
- //
- bi = new BigInteger("153890972191202256150310830154922163807316525358455215516067727076235016932726922093888770552128767458882963869421440585369743", 10);
- if (!bi.isProbablePrime(80)) {
- fail("isProbablePrime failed for: " + bi);
- }
- bi = new BigInteger("2090575416269141767246491983797422123741252476560371649798066134123893524014911825188890458270426076468664046568752890122415061377308817346303546688282957897504000216241497550243010257911214329646877810655164658470278901030511157372440751259674247310396158238588463284702737181653", 10);
- if (!bi.isProbablePrime(80)) {
- fail("isProbablePrime failed for: " + bi);
- }
- //
- for (int bitLength = 100; bitLength <= 600; bitLength += 100) {
- BigInteger a = BigInteger.probablePrime(bitLength, rand);
- BigInteger b = BigInteger.probablePrime(bitLength, rand);
- BigInteger c = a.multiply(b);
- assertFalse("isProbablePrime failed for product of two large primes" +
- a + " * " + b + " = " + c +
- " (bitLength = " + bitLength + ")",
- c.isProbablePrime(80) );
- }
- }
-
- /**
- * java.math.BigInteger#nextProbablePrime()
- */
- public void test_nextProbablePrime() {
- largePrimesProduct(
- new BigInteger("2537895984043447429238717358455377929009126353874925049325287329295635198252046158619999217453233889378619619008359011789"),
- new BigInteger("1711501451602688337873833423534849678524059393231999670806585630179374689152366029939952735718718709436427337762082614710093"),
- "4343612660706993434504106787562106084038357258130862545477481433639575850237346784798851102536616749334772541987502120552264920040629526028540204698334741815536099373917351194423681128374184971846099257056996626343051832131340568120612204287123"
- );
-
- largePrimesProduct(
- new BigInteger("4617974730611208463200675282934641082129817404749925308887287017217158545765190433369842932770197341032031682222405074564586462802072184047198214312142847809259437477387527466762251087500170588962277514858557309036550499896961735701485020851"),
- new BigInteger("4313158964405728158057980867015758419530142215799386331265837224051830838583266274443105715022196238165196727467066901495701708590167750818040112544031694506528759169669442493029999154074962566165293254671176670719518898684698255068313216294333"),
- "19918059106734861363335842730108905466210762564765297409619920041621379008685530738918145604092111306972524565803236031571858280032420140331838737621152630780261815015157696362550138161774466814661069892975003440654998880587960037013294137372709096788892473385003457361736563927256562678181177287998121131179907762285048659075843995525830945659905573174849006768920618442371027575308854641789533211132313916836205357976988977849024687805212304038260207820679964201211309384057458137851"
- );
- }
-
- static void largePrimesProduct(BigInteger a, BigInteger b, String c) {
- BigInteger wp = a.multiply(b);
- assertFalse("isProbablePrime failed for product of two large primes" +
- a + " * " + b + " = " + c,
- wp.isProbablePrime(80) );
- BigInteger wpMinusOne = wp.subtract(BigInteger.ONE);
- BigInteger next = wpMinusOne.nextProbablePrime();
-// System.out.println(c);
-// System.out.println(next);
- assertTrue("nextProbablePrime returns wrong number: " + next +
- "instead of expected: " + c,
- next.toString().equals(c) );
- }
-
- /**
- * java.math.BigInteger#probablePrime(int, java.util.Random)
- */
- public void test_probablePrime() {
- for (int bitLength = 50; bitLength <= 1050; bitLength += 100) {
- BigInteger a = BigInteger.probablePrime(bitLength, rand);
- assertTrue("isProbablePrime(probablePrime()) failed for: " + bi,
- a.isProbablePrime(80));
-// System.out.println(a);
-// BigInteger prime = a.nextProbablePrime();
-// System.out.print("Next Probable Prime is ");
-// System.out.println(prime);
- }
- }
-
-// BEGIN android-added
-// public void testModPowPerformance() {
-// Random rnd = new Random();
-// for (int i = 0; i < 10; i++) {
-// BigInteger a = new BigInteger(512, rnd);
-// BigInteger m = new BigInteger(1024, rnd);
-// BigInteger p = new BigInteger(256, rnd);
-// BigInteger mp = a.modPow(p, m);
-// System.out.println(mp);
-// }
-// }
-
-// shows factor 20 speed up (BIGNUM to Harmony Java):
-// public void testNextProbablePrime() {
-// Random rnd = new Random();
-// rnd.setSeed(0);
-// for (int i = 1; i <= 32; i += 1) {
-// BigInteger a = new BigInteger(i, rnd);
-// System.out.println(a);
-// BigInteger prime = a.nextProbablePrime();
-// System.out.print("Next Probable Prime is ");
-// System.out.println(prime);
-// }
-// for (int i = 1; i <= 32; i += 4) {
-// BigInteger a = new BigInteger(32 * i, rnd);
-// System.out.println(a);
-// BigInteger prime = a.nextProbablePrime();
-// System.out.print("Next Probable Prime is ");
-// System.out.println(prime);
-// }
-// }
-
-// shows factor 20 speed up (BIGNUM to Harmony Java):
-// shows that certainty 80 is "practically aquivalent" to certainty 100
-// public void testPrimeGenPerformance() {
-// Random rnd = new Random();
-// rnd.setSeed(0);
-// for (int i = 1; i <= 32; i +=8 ) {
-// BigInteger a = new BigInteger(32 * i, 80, rnd);
-// System.out.println(a);
-// System.out.println("Now testing it again:");
-// if (a.isProbablePrime(100)) {
-// System.out.println("************************ PASSED! **************************");
-// } else {
-// System.out.println("************************ FAILED!!! **************************");
-// System.out.println("************************ FAILED!!! **************************");
-// System.out.println("************************ FAILED!!! **************************");
-// System.out.println("************************ FAILED!!! **************************");
-// System.out.println("************************ FAILED!!! **************************");
-// System.out.println("************************ FAILED!!! **************************");
-// }
-// }
-// }
-// END android-added
-
-
-
- /**
- * java.math.BigInteger#equals(java.lang.Object)
- */
- public void test_equalsLjava_lang_Object() {
- assertTrue("0=0", zero.equals(BigInteger.valueOf(0)));
- assertTrue("-123=-123", BigInteger.valueOf(-123).equals(
- BigInteger.valueOf(-123)));
- assertTrue("0=1", !zero.equals(one));
- assertTrue("0=-1", !zero.equals(minusOne));
- assertTrue("1=-1", !one.equals(minusOne));
- assertTrue("bi3=bi3", bi3.equals(bi3));
- assertTrue("bi3=copy of bi3", bi3.equals(bi3.negate().negate()));
- assertTrue("bi3=bi2", !bi3.equals(bi2));
- }
-
- /**
- * java.math.BigInteger#compareTo(java.math.BigInteger)
- */
- public void test_compareToLjava_math_BigInteger() {
- assertTrue("Smaller number returned >= 0", one.compareTo(two) < 0);
- assertTrue("Larger number returned >= 0", two.compareTo(one) > 0);
- assertTrue("Equal numbers did not return 0", one.compareTo(one) == 0);
- assertTrue("Neg number messed things up",
- two.negate().compareTo(one) < 0);
- }
-
- /**
- * java.math.BigInteger#intValue()
- */
- public void test_intValue() {
- assertTrue("Incorrect intValue for 2**70",
- twoToTheSeventy.intValue() == 0);
- assertTrue("Incorrect intValue for 2", two.intValue() == 2);
- }
-
- /**
- * java.math.BigInteger#longValue()
- */
- public void test_longValue() {
- assertTrue("Incorrect longValue for 2**70",
- twoToTheSeventy.longValue() == 0);
- assertTrue("Incorrect longValue for 2", two.longValue() == 2);
- }
-
- /**
- * java.math.BigInteger#valueOf(long)
- */
- public void test_valueOfJ() {
- assertTrue("Incurred number returned for 2", BigInteger.valueOf(2L)
- .equals(two));
- assertTrue("Incurred number returned for 200", BigInteger.valueOf(200L)
- .equals(BigInteger.valueOf(139).add(BigInteger.valueOf(61))));
- }
-
- /**
- * java.math.BigInteger#add(java.math.BigInteger)
- */
- public void test_addLjava_math_BigInteger() {
- assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
- .add(aZillion.negate()).equals(aZillion));
- assertTrue("0+0", zero.add(zero).equals(zero));
- assertTrue("0+1", zero.add(one).equals(one));
- assertTrue("1+0", one.add(zero).equals(one));
- assertTrue("1+1", one.add(one).equals(two));
- assertTrue("0+(-1)", zero.add(minusOne).equals(minusOne));
- assertTrue("(-1)+0", minusOne.add(zero).equals(minusOne));
- assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(minusTwo));
- assertTrue("1+(-1)", one.add(minusOne).equals(zero));
- assertTrue("(-1)+1", minusOne.add(one).equals(zero));
-
- for (int i = 0; i < 200; i++) {
- BigInteger midbit = zero.setBit(i);
- assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
- .equals(zero.setBit(i + 1)));
- }
- BigInteger bi2p3 = bi2.add(bi3);
- BigInteger bi3p2 = bi3.add(bi2);
- assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
-
-
- // BESSER UEBERGREIFENDE TESTS MACHEN IN FORM VON STRESS TEST.
- // add large positive + small positive
- BigInteger sum = aZillion;
- BigInteger increment = one;
- for (int i = 0; i < 20; i++) {
-
- }
-
- // add large positive + small negative
-
- // add large negative + small positive
-
- // add large negative + small negative
- }
-
- /**
- * java.math.BigInteger#negate()
- */
- public void test_negate() {
- assertTrue("Single negation of zero did not result in zero", zero
- .negate().equals(zero));
- assertTrue("Single negation resulted in original nonzero number",
- !aZillion.negate().equals(aZillion));
- assertTrue("Double negation did not result in original number",
- aZillion.negate().negate().equals(aZillion));
-
- assertTrue("0.neg", zero.negate().equals(zero));
- assertTrue("1.neg", one.negate().equals(minusOne));
- assertTrue("2.neg", two.negate().equals(minusTwo));
- assertTrue("-1.neg", minusOne.negate().equals(one));
- assertTrue("-2.neg", minusTwo.negate().equals(two));
- assertTrue("0x62EB40FEF85AA9EBL*2.neg", BigInteger.valueOf(
- 0x62EB40FEF85AA9EBL * 2).negate().equals(
- BigInteger.valueOf(-0x62EB40FEF85AA9EBL * 2)));
- for (int i = 0; i < 200; i++) {
- BigInteger midbit = zero.setBit(i);
- BigInteger negate = midbit.negate();
- assertTrue("negate negate", negate.negate().equals(midbit));
- assertTrue("neg fails on bit " + i, midbit.negate().add(midbit)
- .equals(zero));
- }
- }
-
- /**
- * java.math.BigInteger#signum()
- */
- public void test_signum() {
- assertTrue("Wrong positive signum", two.signum() == 1);
- assertTrue("Wrong zero signum", zero.signum() == 0);
- assertTrue("Wrong neg zero signum", zero.negate().signum() == 0);
- assertTrue("Wrong neg signum", two.negate().signum() == -1);
- }
-
- /**
- * java.math.BigInteger#abs()
- */
- public void test_abs() {
- assertTrue("Invalid number returned for zillion", aZillion.negate()
- .abs().equals(aZillion.abs()));
- assertTrue("Invalid number returned for zero neg", zero.negate().abs()
- .equals(zero));
- assertTrue("Invalid number returned for zero", zero.abs().equals(zero));
- assertTrue("Invalid number returned for two", two.negate().abs()
- .equals(two));
- }
-
- /**
- * java.math.BigInteger#pow(int)
- */
- public void test_powI() {
- assertTrue("Incorrect exponent returned for 2**10", two.pow(10).equals(
- twoToTheTen));
- assertTrue("Incorrect exponent returned for 2**70", two.pow(30)
- .multiply(two.pow(40)).equals(twoToTheSeventy));
- assertTrue("Incorrect exponent returned for 10**50", ten.pow(50)
- .equals(aZillion));
- }
-
- /**
- * java.math.BigInteger#modInverse(java.math.BigInteger)
- */
- public void test_modInverseLjava_math_BigInteger() {
- BigInteger a = zero, mod, inv;
- for (int j = 3; j < 50; j++) {
- mod = BigInteger.valueOf(j);
- for (int i = -j + 1; i < j; i++) {
- try {
- a = BigInteger.valueOf(i);
- inv = a.modInverse(mod);
- assertTrue("bad inverse: " + a + " inv mod " + mod
- + " equals " + inv, one.equals(a.multiply(inv).mod(
- mod)));
- assertTrue("inverse greater than modulo: " + a
- + " inv mod " + mod + " equals " + inv, inv
- .compareTo(mod) < 0);
- assertTrue("inverse less than zero: " + a + " inv mod "
- + mod + " equals " + inv, inv
- .compareTo(BigInteger.ZERO) >= 0);
- } catch (ArithmeticException e) {
- assertTrue("should have found inverse for " + a + " mod "
- + mod, !one.equals(a.gcd(mod)));
- }
- }
- }
- for (int j = 1; j < 10; j++) {
- mod = bi2.add(BigInteger.valueOf(j));
- for (int i = 0; i < 20; i++) {
- try {
- a = bi3.add(BigInteger.valueOf(i));
- inv = a.modInverse(mod);
- assertTrue("bad inverse: " + a + " inv mod " + mod
- + " equals " + inv, one.equals(a.multiply(inv).mod(
- mod)));
- assertTrue("inverse greater than modulo: " + a
- + " inv mod " + mod + " equals " + inv, inv
- .compareTo(mod) < 0);
- assertTrue("inverse less than zero: " + a + " inv mod "
- + mod + " equals " + inv, inv
- .compareTo(BigInteger.ZERO) >= 0);
- } catch (ArithmeticException e) {
- assertTrue("should have found inverse for " + a + " mod "
- + mod, !one.equals(a.gcd(mod)));
- }
- }
- }
- }
-
- /**
- * java.math.BigInteger#shiftRight(int)
- */
- public void test_shiftRightI() {
- assertTrue("1 >> 0", BigInteger.valueOf(1).shiftRight(0).equals(
- BigInteger.ONE));
- assertTrue("1 >> 1", BigInteger.valueOf(1).shiftRight(1).equals(
- BigInteger.ZERO));
- assertTrue("1 >> 63", BigInteger.valueOf(1).shiftRight(63).equals(
- BigInteger.ZERO));
- assertTrue("1 >> 64", BigInteger.valueOf(1).shiftRight(64).equals(
- BigInteger.ZERO));
- assertTrue("1 >> 65", BigInteger.valueOf(1).shiftRight(65).equals(
- BigInteger.ZERO));
- assertTrue("1 >> 1000", BigInteger.valueOf(1).shiftRight(1000).equals(
- BigInteger.ZERO));
- assertTrue("-1 >> 0", BigInteger.valueOf(-1).shiftRight(0).equals(
- minusOne));
- assertTrue("-1 >> 1", BigInteger.valueOf(-1).shiftRight(1).equals(
- minusOne));
- assertTrue("-1 >> 63", BigInteger.valueOf(-1).shiftRight(63).equals(
- minusOne));
- assertTrue("-1 >> 64", BigInteger.valueOf(-1).shiftRight(64).equals(
- minusOne));
- assertTrue("-1 >> 65", BigInteger.valueOf(-1).shiftRight(65).equals(
- minusOne));
- assertTrue("-1 >> 1000", BigInteger.valueOf(-1).shiftRight(1000)
- .equals(minusOne));
-
- BigInteger a = BigInteger.ONE;
- BigInteger c = bi3;
- BigInteger E = bi3.negate();
- BigInteger e = E;
- for (int i = 0; i < 200; i++) {
- BigInteger b = BigInteger.ZERO.setBit(i);
- assertTrue("a==b", a.equals(b));
- a = a.shiftLeft(1);
- assertTrue("a non-neg", a.signum() >= 0);
-
- BigInteger d = bi3.shiftRight(i);
- assertTrue("c==d", c.equals(d));
- c = c.shiftRight(1);
- assertTrue(">>1 == /2", d.divide(two).equals(c));
- assertTrue("c non-neg", c.signum() >= 0);
-
- BigInteger f = E.shiftRight(i);
- assertTrue("e==f", e.equals(f));
- e = e.shiftRight(1);
- assertTrue(">>1 == /2", f.subtract(one).divide(two).equals(e));
- assertTrue("e negative", e.signum() == -1);
-
- assertTrue("b >> i", b.shiftRight(i).equals(one));
- assertTrue("b >> i+1", b.shiftRight(i + 1).equals(zero));
- assertTrue("b >> i-1", b.shiftRight(i - 1).equals(two));
- }
- }
-
- /**
- * java.math.BigInteger#shiftLeft(int)
- */
- public void test_shiftLeftI() {
- assertTrue("1 << 0", one.shiftLeft(0).equals(one));
- assertTrue("1 << 1", one.shiftLeft(1).equals(two));
- assertTrue("1 << 63", one.shiftLeft(63).equals(
- new BigInteger("8000000000000000", 16)));
- assertTrue("1 << 64", one.shiftLeft(64).equals(
- new BigInteger("10000000000000000", 16)));
- assertTrue("1 << 65", one.shiftLeft(65).equals(
- new BigInteger("20000000000000000", 16)));
- assertTrue("-1 << 0", minusOne.shiftLeft(0).equals(minusOne));
- assertTrue("-1 << 1", minusOne.shiftLeft(1).equals(minusTwo));
- assertTrue("-1 << 63", minusOne.shiftLeft(63).equals(
- new BigInteger("-9223372036854775808")));
- assertTrue("-1 << 64", minusOne.shiftLeft(64).equals(
- new BigInteger("-18446744073709551616")));
- assertTrue("-1 << 65", minusOne.shiftLeft(65).equals(
- new BigInteger("-36893488147419103232")));
-
- BigInteger a = bi3;
- BigInteger c = minusOne;
- for (int i = 0; i < 200; i++) {
- BigInteger b = bi3.shiftLeft(i);
- assertTrue("a==b", a.equals(b));
- assertTrue("a >> i == bi3", a.shiftRight(i).equals(bi3));
- a = a.shiftLeft(1);
- assertTrue("<<1 == *2", b.multiply(two).equals(a));
- assertTrue("a non-neg", a.signum() >= 0);
- assertTrue("a.bitCount==b.bitCount", a.bitCount() == b.bitCount());
-
- BigInteger d = minusOne.shiftLeft(i);
- assertTrue("c==d", c.equals(d));
- c = c.shiftLeft(1);
- assertTrue("<<1 == *2 negative", d.multiply(two).equals(c));
- assertTrue("c negative", c.signum() == -1);
- assertTrue("d >> i == minusOne", d.shiftRight(i).equals(minusOne));
- }
- }
-
- /**
- * java.math.BigInteger#multiply(java.math.BigInteger)
- */
- public void test_multiplyLjava_math_BigInteger() {
- assertTrue("Incorrect sum--wanted three zillion", aZillion
- .add(aZillion).add(aZillion).equals(
- aZillion.multiply(new BigInteger("3", 10))));
-
- assertTrue("0*0", zero.multiply(zero).equals(zero));
- assertTrue("0*1", zero.multiply(one).equals(zero));
- assertTrue("1*0", one.multiply(zero).equals(zero));
- assertTrue("1*1", one.multiply(one).equals(one));
- assertTrue("0*(-1)", zero.multiply(minusOne).equals(zero));
- assertTrue("(-1)*0", minusOne.multiply(zero).equals(zero));
- assertTrue("(-1)*(-1)", minusOne.multiply(minusOne).equals(one));
- assertTrue("1*(-1)", one.multiply(minusOne).equals(minusOne));
- assertTrue("(-1)*1", minusOne.multiply(one).equals(minusOne));
-
- testAllMults(bi1, bi1, bi11);
- testAllMults(bi2, bi2, bi22);
- testAllMults(bi3, bi3, bi33);
- testAllMults(bi1, bi2, bi12);
- testAllMults(bi1, bi3, bi13);
- testAllMults(bi2, bi3, bi23);
- }
-
- /**
- * java.math.BigInteger#divide(java.math.BigInteger)
- */
- public void test_divideLjava_math_BigInteger() {
- testAllDivs(bi33, bi3);
- testAllDivs(bi22, bi2);
- testAllDivs(bi11, bi1);
- testAllDivs(bi13, bi1);
- testAllDivs(bi13, bi3);
- testAllDivs(bi12, bi1);
- testAllDivs(bi12, bi2);
- testAllDivs(bi23, bi2);
- testAllDivs(bi23, bi3);
- testAllDivs(largePos, bi1);
- testAllDivs(largePos, bi2);
- testAllDivs(largePos, bi3);
- testAllDivs(largeNeg, bi1);
- testAllDivs(largeNeg, bi2);
- testAllDivs(largeNeg, bi3);
- testAllDivs(largeNeg, largePos);
- testAllDivs(largePos, largeNeg);
- testAllDivs(bi3, bi3);
- testAllDivs(bi2, bi2);
- testAllDivs(bi1, bi1);
- testDivRanges(bi1);
- testDivRanges(bi2);
- testDivRanges(bi3);
- testDivRanges(smallPos);
- testDivRanges(largePos);
- testDivRanges(new BigInteger("62EB40FEF85AA9EB", 16));
- testAllDivs(BigInteger.valueOf(0xCC0225953CL), BigInteger
- .valueOf(0x1B937B765L));
-
- try {
- largePos.divide(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi1.divide(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi3.negate().divide(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- zero.divide(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
- }
-
- /**
- * java.math.BigInteger#remainder(java.math.BigInteger)
- */
- public void test_remainderLjava_math_BigInteger() {
- try {
- largePos.remainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi1.remainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi3.negate().remainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- zero.remainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
- }
-
- /**
- * java.math.BigInteger#mod(java.math.BigInteger)
- */
- public void test_modLjava_math_BigInteger() {
- try {
- largePos.mod(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi1.mod(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi3.negate().mod(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- zero.mod(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
- }
-
- /**
- * java.math.BigInteger#divideAndRemainder(java.math.BigInteger)
- */
- public void test_divideAndRemainderLjava_math_BigInteger() {
- try {
- largePos.divideAndRemainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi1.divideAndRemainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- bi3.negate().divideAndRemainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
-
- try {
- zero.divideAndRemainder(zero);
- fail("ArithmeticException expected");
- } catch (ArithmeticException e) {
- }
- }
-
- /**
- * java.math.BigInteger#BigInteger(java.lang.String)
- */
- public void test_ConstructorLjava_lang_String() {
- assertTrue("new(0)", new BigInteger("0").equals(BigInteger.valueOf(0)));
- assertTrue("new(1)", new BigInteger("1").equals(BigInteger.valueOf(1)));
- assertTrue("new(12345678901234)", new BigInteger("12345678901234")
- .equals(BigInteger.valueOf(12345678901234L)));
- assertTrue("new(-1)", new BigInteger("-1").equals(BigInteger
- .valueOf(-1)));
- assertTrue("new(-12345678901234)", new BigInteger("-12345678901234")
- .equals(BigInteger.valueOf(-12345678901234L)));
- }
-
- /**
- * java.math.BigInteger#BigInteger(java.lang.String, int)
- */
- public void test_ConstructorLjava_lang_StringI() {
- assertTrue("new(0,16)", new BigInteger("0", 16).equals(BigInteger
- .valueOf(0)));
- assertTrue("new(1,16)", new BigInteger("1", 16).equals(BigInteger
- .valueOf(1)));
- assertTrue("new(ABF345678901234,16)", new BigInteger("ABF345678901234",
- 16).equals(BigInteger.valueOf(0xABF345678901234L)));
- assertTrue("new(abf345678901234,16)", new BigInteger("abf345678901234",
- 16).equals(BigInteger.valueOf(0xABF345678901234L)));
- assertTrue("new(-1,16)", new BigInteger("-1", 16).equals(BigInteger
- .valueOf(-1)));
- assertTrue("new(-ABF345678901234,16)", new BigInteger(
- "-ABF345678901234", 16).equals(BigInteger
- .valueOf(-0xABF345678901234L)));
- assertTrue("new(-abf345678901234,16)", new BigInteger(
- "-abf345678901234", 16).equals(BigInteger
- .valueOf(-0xABF345678901234L)));
- assertTrue("new(-101010101,2)", new BigInteger("-101010101", 2)
- .equals(BigInteger.valueOf(-341)));
- }
-
- /**
- * java.math.BigInteger#toString()
- */
- public void test_toString() {
- assertTrue("0.toString", "0".equals(BigInteger.valueOf(0).toString()));
- assertTrue("1.toString", "1".equals(BigInteger.valueOf(1).toString()));
- assertTrue("12345678901234.toString", "12345678901234"
- .equals(BigInteger.valueOf(12345678901234L).toString()));
- assertTrue("-1.toString", "-1"
- .equals(BigInteger.valueOf(-1).toString()));
- assertTrue("-12345678901234.toString", "-12345678901234"
- .equals(BigInteger.valueOf(-12345678901234L).toString()));
- }
-
- /**
- * java.math.BigInteger#toString(int)
- */
- public void test_toStringI() {
- assertTrue("0.toString(16)", "0".equals(BigInteger.valueOf(0).toString(
- 16)));
- assertTrue("1.toString(16)", "1".equals(BigInteger.valueOf(1).toString(
- 16)));
- assertTrue("ABF345678901234.toString(16)", "abf345678901234"
- .equals(BigInteger.valueOf(0xABF345678901234L).toString(16)));
- assertTrue("-1.toString(16)", "-1".equals(BigInteger.valueOf(-1)
- .toString(16)));
- assertTrue("-ABF345678901234.toString(16)", "-abf345678901234"
- .equals(BigInteger.valueOf(-0xABF345678901234L).toString(16)));
- assertTrue("-101010101.toString(2)", "-101010101".equals(BigInteger
- .valueOf(-341).toString(2)));
- }
-
- /**
- * java.math.BigInteger#and(java.math.BigInteger)
- */
- public void test_andLjava_math_BigInteger() {
- for (BigInteger[] element : booleanPairs) {
- BigInteger i1 = element[0], i2 = element[1];
- BigInteger res = i1.and(i2);
- assertTrue("symmetry of and", res.equals(i2.and(i1)));
- int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
- for (int i = 0; i < len; i++) {
- assertTrue("and", (i1.testBit(i) && i2.testBit(i)) == res
- .testBit(i));
- }
- }
- }
-
- /**
- * java.math.BigInteger#or(java.math.BigInteger)
- */
- public void test_orLjava_math_BigInteger() {
- for (BigInteger[] element : booleanPairs) {
- BigInteger i1 = element[0], i2 = element[1];
- BigInteger res = i1.or(i2);
- assertTrue("symmetry of or", res.equals(i2.or(i1)));
- int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
- for (int i = 0; i < len; i++) {
- assertTrue("or", (i1.testBit(i) || i2.testBit(i)) == res
- .testBit(i));
- }
- }
- }
-
- /**
- * java.math.BigInteger#xor(java.math.BigInteger)
- */
- public void test_xorLjava_math_BigInteger() {
- for (BigInteger[] element : booleanPairs) {
- BigInteger i1 = element[0], i2 = element[1];
- BigInteger res = i1.xor(i2);
- assertTrue("symmetry of xor", res.equals(i2.xor(i1)));
- int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
- for (int i = 0; i < len; i++) {
- assertTrue("xor", (i1.testBit(i) ^ i2.testBit(i)) == res
- .testBit(i));
- }
- }
- }
-
- /**
- * java.math.BigInteger#not()
- */
- public void test_not() {
- for (BigInteger[] element : booleanPairs) {
- BigInteger i1 = element[0];
- BigInteger res = i1.not();
- int len = i1.bitLength() + 66;
- for (int i = 0; i < len; i++) {
- assertTrue("not", !i1.testBit(i) == res.testBit(i));
- }
- }
- }
-
- /**
- * java.math.BigInteger#andNot(java.math.BigInteger)
- */
- public void test_andNotLjava_math_BigInteger() {
- for (BigInteger[] element : booleanPairs) {
- BigInteger i1 = element[0], i2 = element[1];
- BigInteger res = i1.andNot(i2);
- int len = Math.max(i1.bitLength(), i2.bitLength()) + 66;
- for (int i = 0; i < len; i++) {
- assertTrue("andNot", (i1.testBit(i) && !i2.testBit(i)) == res
- .testBit(i));
- }
- // asymmetrical
- i1 = element[1];
- i2 = element[0];
- res = i1.andNot(i2);
- for (int i = 0; i < len; i++) {
- assertTrue("andNot reversed",
- (i1.testBit(i) && !i2.testBit(i)) == res.testBit(i));
- }
- }
-
- //regression for HARMONY-4653
- try{
- BigInteger.ZERO.andNot(null);
- fail("should throw NPE");
- }catch(Exception e){
- //expected
- }
- BigInteger bi = new BigInteger(0, new byte[]{});
- assertEquals(BigInteger.ZERO, bi.andNot(BigInteger.ZERO));
- }
-
-
- public void testClone() {
- // Regression test for HARMONY-1770
- MyBigInteger myBigInteger = new MyBigInteger("12345");
- myBigInteger = (MyBigInteger) myBigInteger.clone();
- }
-
- static class MyBigInteger extends BigInteger implements Cloneable {
- public MyBigInteger(String val) {
- super(val);
- }
- public Object clone() {
- try {
- return super.clone();
- } catch (CloneNotSupportedException e) {
- throw new AssertionError(e); // android-changed
- }
- }
- }
-
- @Override
- protected void setUp() {
- bi1 = new BigInteger("2436798324768978", 16);
- bi2 = new BigInteger("4576829475724387584378543764555", 16);
- bi3 = new BigInteger("43987298363278574365732645872643587624387563245",
- 16);
-
- bi33 = new BigInteger(
- "10730846694701319120609898625733976090865327544790136667944805934175543888691400559249041094474885347922769807001",
- 10);
- bi22 = new BigInteger(
- "33301606932171509517158059487795669025817912852219962782230629632224456249",
- 10);
- bi11 = new BigInteger("6809003003832961306048761258711296064", 10);
- bi23 = new BigInteger(
- "597791300268191573513888045771594235932809890963138840086083595706565695943160293610527214057",
- 10);
- bi13 = new BigInteger(
- "270307912162948508387666703213038600031041043966215279482940731158968434008",
- 10);
- bi12 = new BigInteger(
- "15058244971895641717453176477697767050482947161656458456", 10);
-
- largePos = new BigInteger(
- "834759814379857314986743298675687569845986736578576375675678998612743867438632986243982098437620983476924376",
- 16);
- smallPos = new BigInteger("48753269875973284765874598630960986276", 16);
- largeNeg = new BigInteger(
- "-878824397432651481891353247987891423768534321387864361143548364457698487264387568743568743265873246576467643756437657436587436",
- 16);
- smallNeg = new BigInteger("-567863254343798609857456273458769843", 16);
- booleanPairs = new BigInteger[][] { { largePos, smallPos },
- { largePos, smallNeg }, { largeNeg, smallPos },
- { largeNeg, smallNeg } };
- }
-
- private void testDiv(BigInteger i1, BigInteger i2) {
- BigInteger q = i1.divide(i2);
- BigInteger r = i1.remainder(i2);
- BigInteger[] temp = i1.divideAndRemainder(i2);
-
- assertTrue("divide and divideAndRemainder do not agree", q
- .equals(temp[0]));
- assertTrue("remainder and divideAndRemainder do not agree", r
- .equals(temp[1]));
- assertTrue("signum and equals(zero) do not agree on quotient", q
- .signum() != 0
- || q.equals(zero));
- assertTrue("signum and equals(zero) do not agree on remainder", r
- .signum() != 0
- || r.equals(zero));
- assertTrue("wrong sign on quotient", q.signum() == 0
- || q.signum() == i1.signum() * i2.signum());
- assertTrue("wrong sign on remainder", r.signum() == 0
- || r.signum() == i1.signum());
- assertTrue("remainder out of range", r.abs().compareTo(i2.abs()) < 0);
- assertTrue("quotient too small", q.abs().add(one).multiply(i2.abs())
- .compareTo(i1.abs()) > 0);
- assertTrue("quotient too large", q.abs().multiply(i2.abs()).compareTo(
- i1.abs()) <= 0);
- BigInteger p = q.multiply(i2);
- BigInteger a = p.add(r);
- assertTrue("(a/b)*b+(a%b) != a", a.equals(i1));
- try {
- BigInteger mod = i1.mod(i2);
- assertTrue("mod is negative", mod.signum() >= 0);
- assertTrue("mod out of range", mod.abs().compareTo(i2.abs()) < 0);
- assertTrue("positive remainder == mod", r.signum() < 0
- || r.equals(mod));
- assertTrue("negative remainder == mod - divisor", r.signum() >= 0
- || r.equals(mod.subtract(i2)));
- } catch (ArithmeticException e) {
- assertTrue("mod fails on negative divisor only", i2.signum() <= 0);
- }
- }
-
- private void testDivRanges(BigInteger i) {
- BigInteger bound = i.multiply(two);
- for (BigInteger j = bound.negate(); j.compareTo(bound) <= 0; j = j
- .add(i)) {
- BigInteger innerbound = j.add(two);
- BigInteger k = j.subtract(two);
- for (; k.compareTo(innerbound) <= 0; k = k.add(one)) {
- testDiv(k, i);
- }
- }
- }
-
- private boolean isPrime(long b) {
- if (b == 2) {
- return true;
- }
- // check for div by 2
- if ((b & 1L) == 0) {
- return false;
- }
- long maxlen = ((long) Math.sqrt(b)) + 2;
- for (long x = 3; x < maxlen; x += 2) {
- if (b % x == 0) {
- return false;
- }
- }
- return true;
- }
-
- private void testAllMults(BigInteger i1, BigInteger i2, BigInteger ans) {
- assertTrue("i1*i2=ans", i1.multiply(i2).equals(ans));
- assertTrue("i2*i1=ans", i2.multiply(i1).equals(ans));
- assertTrue("-i1*i2=-ans", i1.negate().multiply(i2).equals(ans.negate()));
- assertTrue("-i2*i1=-ans", i2.negate().multiply(i1).equals(ans.negate()));
- assertTrue("i1*-i2=-ans", i1.multiply(i2.negate()).equals(ans.negate()));
- assertTrue("i2*-i1=-ans", i2.multiply(i1.negate()).equals(ans.negate()));
- assertTrue("-i1*-i2=ans", i1.negate().multiply(i2.negate()).equals(ans));
- assertTrue("-i2*-i1=ans", i2.negate().multiply(i1.negate()).equals(ans));
- }
-
- private void testAllDivs(BigInteger i1, BigInteger i2) {
- testDiv(i1, i2);
- testDiv(i1.negate(), i2);
- testDiv(i1, i2.negate());
- testDiv(i1.negate(), i2.negate());
- }
-}
diff --git a/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java b/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java
new file mode 100644
index 0000000..167ebe8
--- /dev/null
+++ b/luni/src/test/java/tests/api/java/math/OldBigIntegerTest.java
@@ -0,0 +1,372 @@
+/*
+ * 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.math;
+
+import java.math.BigInteger;
+import java.util.Random;
+
+public class OldBigIntegerTest extends junit.framework.TestCase {
+
+ BigInteger minusOne = new BigInteger("-1", 10);
+
+ BigInteger two = new BigInteger("2", 10);
+
+ BigInteger aZillion = new BigInteger("100000000000000000000000000000000000000000000000000", 10);
+
+ Random rand = new Random();
+
+ BigInteger bi;
+
+ BigInteger bi2;
+
+ BigInteger bi3;
+
+ /**
+ * java.math.BigInteger#BigInteger(int, java.util.Random)
+ */
+ public void test_ConstructorILjava_util_Random() {
+ // regression test for HARMONY-1047
+ try {
+ new BigInteger(128, (Random) null);
+ fail();
+ } catch (NullPointerException expected) {
+ }
+
+ bi = new BigInteger(70, rand);
+ bi2 = new BigInteger(70, rand);
+ assertTrue("Random number is negative", bi.compareTo(BigInteger.ZERO) >= 0);
+ assertTrue("Random number is too big", bi.compareTo(two.pow(70)) < 0);
+ assertTrue(
+ "Two random numbers in a row are the same (might not be a bug but it very likely is)",
+ !bi.equals(bi2));
+ assertTrue("Not zero", new BigInteger(0, rand).equals(BigInteger.ZERO));
+
+ try {
+ new BigInteger(-1, (Random)null);
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException e) {
+ // PASSED
+ }
+ }
+
+ /**
+ * java.math.BigInteger#BigInteger(int, int, java.util.Random)
+ */
+ // BIGNUM returns no Primes smaller than 16 bits.
+ public void test_ConstructorIILjava_util_Random() {
+ BigInteger bi1 = new BigInteger(10, 5, rand);
+ BigInteger bi2 = new BigInteger(10, 5, rand);
+ assertTrue(bi1 + " is negative", bi1.compareTo(BigInteger.ZERO) >= 0);
+ assertTrue(bi1 + " is too big", bi1.compareTo(new BigInteger("1024", 10)) < 0);
+ assertTrue(bi2 + " is negative", bi2.compareTo(BigInteger.ZERO) >= 0);
+ assertTrue(bi2 + " is too big", bi2.compareTo(new BigInteger("1024", 10)) < 0);
+
+ Random rand = new Random();
+ BigInteger bi;
+ int certainty[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ Integer.MIN_VALUE, Integer.MIN_VALUE + 1, -2, -1 };
+ for (int i = 2; i <= 20; i++) {
+ for (int c = 0; c < certainty.length; c++) {
+ bi = new BigInteger(i, c, rand); // Create BigInteger
+ assertEquals(i, bi.bitLength());
+ }
+ }
+
+ try {
+ new BigInteger(1, 80, (Random)null);
+ fail("ArithmeticException expected");
+ } catch (ArithmeticException expected) {
+ }
+
+ try {
+ new BigInteger(-1, (Random)null);
+ fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException expected) {
+ }
+ }
+
+// public void test_SpecialPrimes() {
+// System.out.println("test_SpecialPrimes");
+// final BigInteger TWO = BigInteger.valueOf(2);
+// BigInteger p, q;
+// for (;;) {
+// p = new BigInteger(1024, 23, new Random());
+// q = p.subtract(BigInteger.ONE).divide(TWO);
+// if (q.isProbablePrime(20)) {
+// System.out.println(q);
+// System.out.println(p);
+// break;
+// }
+// System.out.print(".");
+// }
+// fail("isProbablePrime failed for: " + bi);
+// }
+
+ /**
+ * java.math.BigInteger#isProbablePrime(int)
+ */
+ public void test_isProbablePrimeI() {
+ int fails = 0;
+ bi = new BigInteger(20, 20, rand);
+ if (!bi.isProbablePrime(17)) {
+ fails++;
+ }
+ bi = new BigInteger("4", 10);
+ if (bi.isProbablePrime(17)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ bi = BigInteger.valueOf(17L * 13L);
+ if (bi.isProbablePrime(17)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ for (long a = 2; a < 1000; a++) {
+ if (isPrime(a)) {
+ assertTrue("false negative on prime number <1000", BigInteger
+ .valueOf(a).isProbablePrime(5));
+ } else if (BigInteger.valueOf(a).isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + a);
+ fails++;
+ }
+ }
+ for (int a = 0; a < 1000; a++) {
+ bi = BigInteger.valueOf(rand.nextInt(1000000)).multiply(
+ BigInteger.valueOf(rand.nextInt(1000000)));
+ if (bi.isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + bi);
+ fails++;
+ }
+ }
+ for (int a = 0; a < 200; a++) {
+ bi = new BigInteger(70, rand).multiply(new BigInteger(70, rand));
+ if (bi.isProbablePrime(17)) {
+ System.out.println("isProbablePrime failed for: " + bi);
+ fails++;
+ }
+ }
+ assertTrue("Too many false positives - may indicate a problem",
+ fails <= 1);
+
+ //
+ // And now some tests on real big integers:
+ //
+ bi = new BigInteger("153890972191202256150310830154922163807316525358455215516067727076235016932726922093888770552128767458882963869421440585369743", 10);
+ if (!bi.isProbablePrime(80)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ bi = new BigInteger("2090575416269141767246491983797422123741252476560371649798066134123893524014911825188890458270426076468664046568752890122415061377308817346303546688282957897504000216241497550243010257911214329646877810655164658470278901030511157372440751259674247310396158238588463284702737181653", 10);
+ if (!bi.isProbablePrime(80)) {
+ fail("isProbablePrime failed for: " + bi);
+ }
+ //
+ for (int bitLength = 100; bitLength <= 600; bitLength += 100) {
+ BigInteger a = BigInteger.probablePrime(bitLength, rand);
+ BigInteger b = BigInteger.probablePrime(bitLength, rand);
+ BigInteger c = a.multiply(b);
+ assertFalse("isProbablePrime failed for product of two large primes" +
+ a + " * " + b + " = " + c +
+ " (bitLength = " + bitLength + ")",
+ c.isProbablePrime(80) );
+ }
+ }
+
+ /**
+ * java.math.BigInteger#nextProbablePrime()
+ */
+ public void test_nextProbablePrime() {
+ largePrimesProduct(
+ new BigInteger("2537895984043447429238717358455377929009126353874925049325287329295635198252046158619999217453233889378619619008359011789"),
+ new BigInteger("1711501451602688337873833423534849678524059393231999670806585630179374689152366029939952735718718709436427337762082614710093"),
+ "4343612660706993434504106787562106084038357258130862545477481433639575850237346784798851102536616749334772541987502120552264920040629526028540204698334741815536099373917351194423681128374184971846099257056996626343051832131340568120612204287123"
+ );
+
+ largePrimesProduct(
+ new BigInteger("4617974730611208463200675282934641082129817404749925308887287017217158545765190433369842932770197341032031682222405074564586462802072184047198214312142847809259437477387527466762251087500170588962277514858557309036550499896961735701485020851"),
+ new BigInteger("4313158964405728158057980867015758419530142215799386331265837224051830838583266274443105715022196238165196727467066901495701708590167750818040112544031694506528759169669442493029999154074962566165293254671176670719518898684698255068313216294333"),
+ "19918059106734861363335842730108905466210762564765297409619920041621379008685530738918145604092111306972524565803236031571858280032420140331838737621152630780261815015157696362550138161774466814661069892975003440654998880587960037013294137372709096788892473385003457361736563927256562678181177287998121131179907762285048659075843995525830945659905573174849006768920618442371027575308854641789533211132313916836205357976988977849024687805212304038260207820679964201211309384057458137851"
+ );
+ }
+
+ static void largePrimesProduct(BigInteger a, BigInteger b, String c) {
+ BigInteger wp = a.multiply(b);
+ assertFalse("isProbablePrime failed for product of two large primes" +
+ a + " * " + b + " = " + c,
+ wp.isProbablePrime(80) );
+ BigInteger wpMinusOne = wp.subtract(BigInteger.ONE);
+ BigInteger next = wpMinusOne.nextProbablePrime();
+// System.out.println(c);
+// System.out.println(next);
+ assertTrue("nextProbablePrime returns wrong number: " + next +
+ "instead of expected: " + c,
+ next.toString().equals(c) );
+ }
+
+ /**
+ * java.math.BigInteger#probablePrime(int, java.util.Random)
+ */
+ public void test_probablePrime() {
+ for (int bitLength = 50; bitLength <= 1050; bitLength += 100) {
+ BigInteger a = BigInteger.probablePrime(bitLength, rand);
+ assertTrue("isProbablePrime(probablePrime()) failed for: " + bi,
+ a.isProbablePrime(80));
+// System.out.println(a);
+// BigInteger prime = a.nextProbablePrime();
+// System.out.print("Next Probable Prime is ");
+// System.out.println(prime);
+ }
+ }
+
+// BEGIN android-added
+// public void testModPowPerformance() {
+// Random rnd = new Random();
+// for (int i = 0; i < 10; i++) {
+// BigInteger a = new BigInteger(512, rnd);
+// BigInteger m = new BigInteger(1024, rnd);
+// BigInteger p = new BigInteger(256, rnd);
+// BigInteger mp = a.modPow(p, m);
+// System.out.println(mp);
+// }
+// }
+
+// shows factor 20 speed up (BIGNUM to Harmony Java):
+// public void testNextProbablePrime() {
+// Random rnd = new Random();
+// rnd.setSeed(0);
+// for (int i = 1; i <= 32; i += 1) {
+// BigInteger a = new BigInteger(i, rnd);
+// System.out.println(a);
+// BigInteger prime = a.nextProbablePrime();
+// System.out.print("Next Probable Prime is ");
+// System.out.println(prime);
+// }
+// for (int i = 1; i <= 32; i += 4) {
+// BigInteger a = new BigInteger(32 * i, rnd);
+// System.out.println(a);
+// BigInteger prime = a.nextProbablePrime();
+// System.out.print("Next Probable Prime is ");
+// System.out.println(prime);
+// }
+// }
+
+// shows factor 20 speed up (BIGNUM to Harmony Java):
+// shows that certainty 80 is "practically aquivalent" to certainty 100
+// public void testPrimeGenPerformance() {
+// Random rnd = new Random();
+// rnd.setSeed(0);
+// for (int i = 1; i <= 32; i +=8 ) {
+// BigInteger a = new BigInteger(32 * i, 80, rnd);
+// System.out.println(a);
+// System.out.println("Now testing it again:");
+// if (a.isProbablePrime(100)) {
+// System.out.println("************************ PASSED! **************************");
+// } else {
+// System.out.println("************************ FAILED!!! **************************");
+// System.out.println("************************ FAILED!!! **************************");
+// System.out.println("************************ FAILED!!! **************************");
+// System.out.println("************************ FAILED!!! **************************");
+// System.out.println("************************ FAILED!!! **************************");
+// System.out.println("************************ FAILED!!! **************************");
+// }
+// }
+// }
+// END android-added
+
+
+
+ /**
+ * java.math.BigInteger#add(java.math.BigInteger)
+ */
+ public void test_addLjava_math_BigInteger() {
+ assertTrue("Incorrect sum--wanted a zillion", aZillion.add(aZillion)
+ .add(aZillion.negate()).equals(aZillion));
+ assertTrue("0+0", BigInteger.ZERO.add(BigInteger.ZERO).equals(BigInteger.ZERO));
+ assertTrue("0+1", BigInteger.ZERO.add(BigInteger.ONE).equals(BigInteger.ONE));
+ assertTrue("1+0", BigInteger.ONE.add(BigInteger.ZERO).equals(BigInteger.ONE));
+ assertTrue("1+1", BigInteger.ONE.add(BigInteger.ONE).equals(two));
+ assertTrue("0+(-1)", BigInteger.ZERO.add(minusOne).equals(minusOne));
+ assertTrue("(-1)+0", minusOne.add(BigInteger.ZERO).equals(minusOne));
+ assertTrue("(-1)+(-1)", minusOne.add(minusOne).equals(new BigInteger("-2", 10)));
+ assertTrue("1+(-1)", BigInteger.ONE.add(minusOne).equals(BigInteger.ZERO));
+ assertTrue("(-1)+1", minusOne.add(BigInteger.ONE).equals(BigInteger.ZERO));
+
+ for (int i = 0; i < 200; i++) {
+ BigInteger midbit = BigInteger.ZERO.setBit(i);
+ assertTrue("add fails to carry on bit " + i, midbit.add(midbit)
+ .equals(BigInteger.ZERO.setBit(i + 1)));
+ }
+ BigInteger bi2p3 = bi2.add(bi3);
+ BigInteger bi3p2 = bi3.add(bi2);
+ assertTrue("bi2p3=bi3p2", bi2p3.equals(bi3p2));
+
+
+ // BESSER UEBERGREIFENDE TESTS MACHEN IN FORM VON STRESS TEST.
+ // add large positive + small positive
+ BigInteger sum = aZillion;
+ BigInteger increment = BigInteger.ONE;
+ for (int i = 0; i < 20; i++) {
+
+ }
+
+ // add large positive + small negative
+
+ // add large negative + small positive
+
+ // add large negative + small negative
+ }
+
+ public void testClone() {
+ // Regression test for HARMONY-1770
+ MyBigInteger myBigInteger = new MyBigInteger("12345");
+ myBigInteger = (MyBigInteger) myBigInteger.clone();
+ }
+
+ static class MyBigInteger extends BigInteger implements Cloneable {
+ public MyBigInteger(String val) {
+ super(val);
+ }
+ public Object clone() {
+ try {
+ return super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e); // android-changed
+ }
+ }
+ }
+
+ @Override
+ protected void setUp() {
+ bi2 = new BigInteger("4576829475724387584378543764555", 16);
+ bi3 = new BigInteger("43987298363278574365732645872643587624387563245", 16);
+ }
+
+ private boolean isPrime(long b) {
+ if (b == 2) {
+ return true;
+ }
+ // check for div by 2
+ if ((b & 1L) == 0) {
+ return false;
+ }
+ long maxlen = ((long) Math.sqrt(b)) + 2;
+ for (long x = 3; x < maxlen; x += 2) {
+ if (b % x == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/luni/src/test/java/tests/api/java/util/CurrencyTest.java b/luni/src/test/java/tests/api/java/util/CurrencyTest.java
index c43d339..82fd7cf 100644
--- a/luni/src/test/java/tests/api/java/util/CurrencyTest.java
+++ b/luni/src/test/java/tests/api/java/util/CurrencyTest.java
@@ -17,8 +17,6 @@
package tests.api.java.util;
-import tests.support.Support_Locale;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
diff --git a/luni/src/test/java/tests/api/java/util/LocaleTest.java b/luni/src/test/java/tests/api/java/util/LocaleTest.java
index 55c8397..7615a76 100644
--- a/luni/src/test/java/tests/api/java/util/LocaleTest.java
+++ b/luni/src/test/java/tests/api/java/util/LocaleTest.java
@@ -17,8 +17,6 @@
package tests.api.java.util;
-import tests.support.Support_Locale;
-
import java.security.Permission;
import java.util.Arrays;
import java.util.HashSet;
@@ -168,10 +166,23 @@
assertEquals("Failed to get locale", "fr_CA_WIN32", x.toString());
}
+ /**
+ * java.util.Locale#getDisplayCountry()
+ */
+ public void test_getDisplayCountry() {
+ // Test for method java.lang.String java.util.Locale.getDisplayCountry()
+ assertTrue("Returned incorrect country: "
+ + testLocale.getDisplayCountry(), testLocale
+ .getDisplayCountry().equals("Canada"));
+
+ // Regression for Harmony-1146
+ Locale l_countryCD = new Locale("", "CD");
+ assertEquals("Congo [DRC]",
+ l_countryCD.getDisplayCountry());
+ }
+
public void test_getDisplayCountryLjava_util_Locale() {
- if (Support_Locale.isLocaleAvailable(Locale.ITALY)) {
- assertEquals("Returned incorrect country", "Italie", Locale.ITALY.getDisplayCountry(l));
- }
+ assertEquals("Italie", Locale.ITALY.getDisplayCountry(new Locale("fr", "CA", "WIN32")));
}
/**
@@ -190,19 +201,15 @@
}
public void test_getDisplayLanguageLjava_util_Locale() {
- if (Support_Locale.isLocaleAvailable(testLocale)) {
- assertEquals("anglais", testLocale.getDisplayLanguage(l));
- }
+ assertEquals("anglais", new Locale("en", "CA", "WIN32").getDisplayLanguage(l));
}
public void test_getDisplayName() {
- assertEquals("English (Canada,WIN32)", testLocale.getDisplayName());
+ assertEquals("English (Canada,WIN32)", new Locale("en", "CA", "WIN32").getDisplayName());
}
public void test_getDisplayNameLjava_util_Locale() {
- if (Support_Locale.isLocaleAvailable(testLocale)) {
- assertEquals("anglais (Canada,WIN32)", testLocale.getDisplayName(l));
- }
+ assertEquals("anglais (Canada,WIN32)", new Locale("en", "CA", "WIN32").getDisplayName(l));
}
/**
@@ -343,8 +350,7 @@
*/
public void test_toString() {
// Test for method java.lang.String java.util.Locale.toString()
- assertEquals("Returned incorrect string representation", "en_CA_WIN32", testLocale
- .toString());
+ assertEquals("en_CA_WIN32", new Locale("en", "CA", "WIN32").toString());
Locale l = new Locale("en", "");
assertEquals("Wrong representation 1", "en", l.toString());
diff --git a/luni/src/test/java/tests/api/java/util/TimerTest.java b/luni/src/test/java/tests/api/java/util/TimerTest.java
index b09fa45..739c018 100644
--- a/luni/src/test/java/tests/api/java/util/TimerTest.java
+++ b/luni/src/test/java/tests/api/java/util/TimerTest.java
@@ -22,12 +22,13 @@
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicReference;
+import junit.framework.TestCase;
-public class TimerTest extends junit.framework.TestCase {
+public class TimerTest extends TestCase {
int timerCounter = 0;
- Object sync = new Object();
+ private final Object sync = new Object();
/**
* Warning: These tests have the possibility to leave a VM hanging if the
@@ -59,14 +60,17 @@
synchronized (this) {
wasRun++;
}
- if (incrementCount)
+ if (incrementCount) {
timerCounter++;
- if (terminateCount == timerCounter && timer != null)
+ }
+ if (terminateCount == timerCounter && timer != null) {
timer.cancel();
+ }
if (sleepInRun) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
}
synchronized (sync) {
@@ -91,19 +95,16 @@
}
}
- private void awaitRun(TimerTestTask task) {
+ private void awaitRun(TimerTestTask task) throws Exception {
while (task.wasRun() == 0) {
- try {
- Thread.sleep(150);
- } catch (InterruptedException e) {
- }
+ Thread.sleep(150);
}
}
/**
* java.util.Timer#Timer(boolean)
*/
- public void test_ConstructorZ() {
+ public void test_ConstructorZ() throws Exception {
Timer t = null;
try {
// Ensure a task is run
@@ -122,7 +123,7 @@
/**
* java.util.Timer#Timer()
*/
- public void test_Constructor() {
+ public void test_Constructor() throws Exception {
Timer t = null;
try {
// Ensure a task is run
@@ -141,7 +142,7 @@
/**
* java.util.Timer#Timer(String, boolean)
*/
- public void test_ConstructorSZ() {
+ public void test_ConstructorSZ() throws Exception {
Timer t = null;
try {
// Ensure a task is run
@@ -157,23 +158,21 @@
try {
new Timer(null, true);
- fail("NullPointerException expected");
- } catch (NullPointerException e) {
- //expected
+ fail();
+ } catch (NullPointerException expected) {
}
try {
new Timer(null, false);
- fail("NullPointerException expected");
- } catch (NullPointerException e) {
- //expected
+ fail();
+ } catch (NullPointerException expected) {
}
}
/**
* java.util.Timer#Timer(String)
*/
- public void test_ConstructorS() {
+ public void test_ConstructorS() throws Exception {
Timer t = null;
try {
// Ensure a task is run
@@ -189,31 +188,26 @@
try {
new Timer(null);
- fail("NullPointerException expected");
- } catch (NullPointerException e) {
- //expected
+ fail();
+ } catch (NullPointerException expected) {
}
}
/**
* java.util.Timer#cancel()
*/
- public void test_cancel() {
+ public void test_cancel() throws Exception {
Timer t = null;
try {
// Ensure a task throws an IllegalStateException after cancelled
t = new Timer();
TimerTestTask testTask = new TimerTestTask();
t.cancel();
- boolean exception = false;
try {
t.schedule(testTask, 100, 200);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after Timer.cancel() should throw exception",
- exception);
// Ensure a task is run but not after cancel
t = new Timer();
@@ -222,13 +216,10 @@
awaitRun(testTask);
t.cancel();
synchronized (sync) {
- try {
- sync.wait(500);
- } catch (InterruptedException e) {
- }
+ sync.wait(500);
}
assertEquals("TimerTask.run() method should not have been called after cancel",
- 1, testTask.wasRun());
+ 1, testTask.wasRun());
// Ensure you can call cancel more than once
t = new Timer();
@@ -239,13 +230,10 @@
t.cancel();
t.cancel();
synchronized (sync) {
- try {
- sync.wait(500);
- } catch (InterruptedException e) {
- }
+ sync.wait(500);
}
assertEquals("TimerTask.run() method should not have been called after cancel",
- 1, testTask.wasRun());
+ 1, testTask.wasRun());
// Ensure that a call to cancel from within a timer ensures no more
// run
@@ -255,23 +243,21 @@
testTask.terminateCount(5); // Terminate after 5 runs
t.schedule(testTask, 100, 100);
synchronized (sync) {
- try {
- sync.wait(200);
- sync.wait(200);
- sync.wait(200);
- sync.wait(200);
- sync.wait(200);
- sync.wait(200);
- } catch (InterruptedException e) {
- }
+ sync.wait(200);
+ assertEquals(1, testTask.wasRun());
+ sync.wait(200);
+ assertEquals(2, testTask.wasRun());
+ sync.wait(200);
+ assertEquals(3, testTask.wasRun());
+ sync.wait(200);
+ assertEquals(4, testTask.wasRun());
+ sync.wait(200);
+ assertEquals(5, testTask.wasRun());
+ sync.wait(200);
+ assertEquals(5, testTask.wasRun());
}
- assertTrue("TimerTask.run() method should be called 5 times not "
- + testTask.wasRun(), testTask.wasRun() == 5);
t.cancel();
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- }
+ Thread.sleep(200);
} finally {
if (t != null)
t.cancel();
@@ -316,7 +302,7 @@
/**
* java.util.Timer#schedule(java.util.TimerTask, java.util.Date)
*/
- public void test_scheduleLjava_util_TimerTaskLjava_util_Date() {
+ public void test_scheduleLjava_util_TimerTaskLjava_util_Date() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
@@ -324,15 +310,11 @@
TimerTestTask testTask = new TimerTestTask();
Date d = new Date(System.currentTimeMillis() + 100);
t.cancel();
- boolean exception = false;
try {
t.schedule(testTask, d);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalStateException if task already
// cancelled
@@ -340,15 +322,11 @@
testTask = new TimerTestTask();
d = new Date(System.currentTimeMillis() + 100);
testTask.cancel();
- exception = false;
try {
t.schedule(testTask, d);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after cancelling it should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after cancelling it should throw exception",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if delay is
@@ -356,58 +334,41 @@
t = new Timer();
testTask = new TimerTestTask();
d = new Date(-100);
- exception = false;
try {
t.schedule(testTask, d);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative date should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative date should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the task is null
t = new Timer();
- exception = false;
d = new Date(System.currentTimeMillis() + 100);
try {
t.schedule(null, d);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null task should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null task should throw NullPointerException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the date is null
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, null);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null date should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null date should throw NullPointerException",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
d = new Date(-100);
- exception = false;
try {
t.schedule(null, d);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task with negative date should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task with negative date should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure a task is run
@@ -436,13 +397,9 @@
testTask.incrementCount(true);
d = new Date(System.currentTimeMillis() + 10);
t.schedule(testTask, d);
- try {
- Thread.sleep(400);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "Multiple tasks should have incremented counter 4 times not "
- + timerCounter, timerCounter == 4);
+ Thread.sleep(400);
+ assertTrue("Multiple tasks should have incremented counter 4 times not "
+ + timerCounter, timerCounter == 4);
t.cancel();
} finally {
if (t != null)
@@ -453,79 +410,58 @@
/**
* java.util.Timer#schedule(java.util.TimerTask, long)
*/
- public void test_scheduleLjava_util_TimerTaskJ() {
+ public void test_scheduleLjava_util_TimerTaskJ() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
t = new Timer();
TimerTestTask testTask = new TimerTestTask();
t.cancel();
- boolean exception = false;
try {
t.schedule(testTask, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalStateException if task already
// cancelled
t = new Timer();
testTask = new TimerTestTask();
testTask.cancel();
- exception = false;
try {
t.schedule(testTask, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after cancelling it should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after cancelling it should throw exception",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if delay is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, -100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative delay should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the task is null
t = new Timer();
- exception = false;
try {
t.schedule(null, 10);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null task should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null task should throw NullPointerException",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
- exception = false;
try {
t.schedule(null, -10);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task with negative delays should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task with negative delays should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure a task is run
@@ -549,13 +485,9 @@
testTask = new TimerTestTask();
testTask.incrementCount(true);
t.schedule(testTask, 10);
- try {
- Thread.sleep(400);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "Multiple tasks should have incremented counter 4 times not "
- + timerCounter, timerCounter == 4);
+ Thread.sleep(400);
+ assertTrue("Multiple tasks should have incremented counter 4 times not "
+ + timerCounter, timerCounter == 4);
t.cancel();
} finally {
if (t != null)
@@ -566,122 +498,89 @@
/**
* java.util.Timer#schedule(java.util.TimerTask, long, long)
*/
- public void test_scheduleLjava_util_TimerTaskJJ() {
+ public void test_scheduleLjava_util_TimerTaskJJ() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
t = new Timer();
TimerTestTask testTask = new TimerTestTask();
t.cancel();
- boolean exception = false;
try {
t.schedule(testTask, 100, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalStateException if task already
// cancelled
t = new Timer();
testTask = new TimerTestTask();
testTask.cancel();
- exception = false;
try {
t.schedule(testTask, 100, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after cancelling it should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after cancelling it should throw exception",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if delay is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, -100, 100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative delay should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if period is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, 100, -100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative period should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative period should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if period is
// zero
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, 100, 0);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with 0 period should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with 0 period should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the task is null
t = new Timer();
- exception = false;
try {
t.schedule(null, 10, 10);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null task should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null task should throw NullPointerException",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
- exception = false;
try {
t.schedule(null, -10, -10);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task with negative delays should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task with negative delays should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure a task is run at least twice
t = new Timer();
testTask = new TimerTestTask();
t.schedule(testTask, 100, 100);
- try {
- Thread.sleep(400);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "TimerTask.run() method should have been called at least twice ("
- + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+ Thread.sleep(400);
+ assertTrue("TimerTask.run() method should have been called at least twice ("
+ + testTask.wasRun() + ")", testTask.wasRun() >= 2);
t.cancel();
// Ensure multiple tasks are run
@@ -698,13 +597,9 @@
testTask = new TimerTestTask();
testTask.incrementCount(true);
t.schedule(testTask, 100, 200); // at least 4 times
- try {
- Thread.sleep(1200); // Allowed more room for error
- } catch (InterruptedException e) {
- }
- assertTrue(
- "Multiple tasks should have incremented counter 24 times not "
- + timerCounter, timerCounter >= 24);
+ Thread.sleep(1200); // Allowed more room for error
+ assertTrue("Multiple tasks should have incremented counter 24 times not "
+ + timerCounter, timerCounter >= 24);
t.cancel();
} finally {
if (t != null)
@@ -716,7 +611,7 @@
* java.util.Timer#schedule(java.util.TimerTask, java.util.Date,
* long)
*/
- public void test_scheduleLjava_util_TimerTaskLjava_util_DateJ() {
+ public void test_scheduleLjava_util_TimerTaskLjava_util_DateJ() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
@@ -724,15 +619,11 @@
TimerTestTask testTask = new TimerTestTask();
Date d = new Date(System.currentTimeMillis() + 100);
t.cancel();
- boolean exception = false;
try {
t.schedule(testTask, d, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalStateException if task already
// cancelled
@@ -740,15 +631,11 @@
d = new Date(System.currentTimeMillis() + 100);
testTask = new TimerTestTask();
testTask.cancel();
- exception = false;
try {
t.schedule(testTask, d, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("Scheduling a task after cancelling it should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "Scheduling a task after cancelling it should throw exception",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if delay is
@@ -756,15 +643,11 @@
t = new Timer();
d = new Date(-100);
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, d, 100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative delay should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative delay should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if period is
@@ -772,58 +655,41 @@
t = new Timer();
d = new Date(System.currentTimeMillis() + 100);
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, d, -100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a task with negative period should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a task with negative period should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the task is null
t = new Timer();
d = new Date(System.currentTimeMillis() + 100);
- exception = false;
try {
t.schedule(null, d, 10);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null task should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null task should throw NullPointerException",
- exception);
t.cancel();
// Ensure a Timer throws a NullPointerException if the date is null
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.schedule(testTask, null, 10);
- } catch (NullPointerException e) {
- exception = true;
+ fail("Scheduling a null task should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "Scheduling a null task should throw NullPointerException",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
d = new Date(-100);
- exception = false;
try {
t.schedule(null, d, 10);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task with negative dates should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task with negative dates should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure a task is run at least twice
@@ -831,13 +697,9 @@
d = new Date(System.currentTimeMillis() + 100);
testTask = new TimerTestTask();
t.schedule(testTask, d, 100);
- try {
- Thread.sleep(800);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "TimerTask.run() method should have been called at least twice ("
- + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+ Thread.sleep(800);
+ assertTrue("TimerTask.run() method should have been called at least twice ("
+ + testTask.wasRun() + ")", testTask.wasRun() >= 2);
t.cancel();
// Ensure multiple tasks are run
@@ -858,13 +720,9 @@
testTask.incrementCount(true);
d = new Date(System.currentTimeMillis() + 100);
t.schedule(testTask, d, 200); // at least 4 times
- try {
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "Multiple tasks should have incremented counter 24 times not "
- + timerCounter, timerCounter >= 24);
+ Thread.sleep(3000);
+ assertTrue("Multiple tasks should have incremented counter 24 times not "
+ + timerCounter, timerCounter >= 24);
t.cancel();
} finally {
if (t != null)
@@ -876,64 +734,48 @@
* java.util.Timer#scheduleAtFixedRate(java.util.TimerTask, long,
* long)
*/
- public void test_scheduleAtFixedRateLjava_util_TimerTaskJJ() {
+ public void test_scheduleAtFixedRateLjava_util_TimerTaskJJ() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
t = new Timer();
TimerTestTask testTask = new TimerTestTask();
t.cancel();
- boolean exception = false;
try {
t.scheduleAtFixedRate(testTask, 100, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("scheduleAtFixedRate after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "scheduleAtFixedRate after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalArgumentException if delay is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.scheduleAtFixedRate(testTask, -100, 100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("scheduleAtFixedRate with negative delay should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "scheduleAtFixedRate with negative delay should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if period is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.scheduleAtFixedRate(testTask, 100, -100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("scheduleAtFixedRate with negative period should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a task is run at least twice
t = new Timer();
testTask = new TimerTestTask();
t.scheduleAtFixedRate(testTask, 100, 100);
- try {
- Thread.sleep(400);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "TimerTask.run() method should have been called at least twice ("
- + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+ Thread.sleep(400);
+ assertTrue("TimerTask.run() method should have been called at least twice ("
+ + testTask.wasRun() + ")", testTask.wasRun() >= 2);
t.cancel();
class SlowThenFastTask extends TimerTask {
@@ -953,6 +795,7 @@
try {
Thread.sleep(200);
} catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
}
}
@@ -972,13 +815,10 @@
// at least 9 times even when asleep
t.scheduleAtFixedRate(slowThenFastTask, 100, 100);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
+ Thread.sleep(1000);
long lastDelta = slowThenFastTask.lastDelta();
assertTrue("Fixed Rate Schedule should catch up, but is off by "
- + lastDelta + " ms", slowThenFastTask.lastDelta < 300);
+ + lastDelta + " ms", slowThenFastTask.lastDelta < 300);
t.cancel();
} finally {
if (t != null)
@@ -990,96 +830,70 @@
* java.util.Timer#scheduleAtFixedRate(java.util.TimerTask,
* java.util.Date, long)
*/
- public void test_scheduleAtFixedRateLjava_util_TimerTaskLjava_util_DateJ() {
+ public void test_scheduleAtFixedRateLjava_util_TimerTaskLjava_util_DateJ() throws Exception {
Timer t = null;
try {
// Ensure a Timer throws an IllegalStateException after cancelled
t = new Timer();
TimerTestTask testTask = new TimerTestTask();
t.cancel();
- boolean exception = false;
Date d = new Date(System.currentTimeMillis() + 100);
try {
t.scheduleAtFixedRate(testTask, d, 100);
- } catch (IllegalStateException e) {
- exception = true;
+ fail("scheduleAtFixedRate after Timer.cancel() should throw exception");
+ } catch (IllegalStateException expected) {
}
- assertTrue(
- "scheduleAtFixedRate after Timer.cancel() should throw exception",
- exception);
// Ensure a Timer throws an IllegalArgumentException if delay is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
d = new Date(-100);
try {
t.scheduleAtFixedRate(testTask, d, 100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("scheduleAtFixedRate with negative Date should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "scheduleAtFixedRate with negative Date should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an IllegalArgumentException if period is
// negative
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.scheduleAtFixedRate(testTask, d, -100);
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("scheduleAtFixedRate with negative period should throw IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "scheduleAtFixedRate with negative period should throw IllegalArgumentException",
- exception);
t.cancel();
// Ensure a Timer throws an NullPointerException if date is Null
t = new Timer();
testTask = new TimerTestTask();
- exception = false;
try {
t.scheduleAtFixedRate(testTask, null, 100);
- } catch (NullPointerException e) {
- exception = true;
+ fail("scheduleAtFixedRate with null date should throw NullPointerException");
+ } catch (NullPointerException expected) {
}
- assertTrue(
- "scheduleAtFixedRate with null date should throw NullPointerException",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
- exception = false;
d = new Date(-100);
try {
t.scheduleAtFixedRate(null, d, 10);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task with negative date should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task with negative date should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure proper sequence of exceptions
t = new Timer();
- exception = false;
try {
t.scheduleAtFixedRate(null, null, -10);
- } catch (NullPointerException e) {
- } catch (IllegalArgumentException e) {
- exception = true;
+ fail("Scheduling a null task & null date & negative period should throw IllegalArgumentException first");
+ } catch (IllegalArgumentException expected) {
}
- assertTrue(
- "Scheduling a null task & null date & negative period should throw IllegalArgumentException first",
- exception);
t.cancel();
// Ensure a task is run at least twice
@@ -1087,13 +901,9 @@
testTask = new TimerTestTask();
d = new Date(System.currentTimeMillis() + 100);
t.scheduleAtFixedRate(testTask, d, 100);
- try {
- Thread.sleep(400);
- } catch (InterruptedException e) {
- }
- assertTrue(
- "TimerTask.run() method should have been called at least twice ("
- + testTask.wasRun() + ")", testTask.wasRun() >= 2);
+ Thread.sleep(400);
+ assertTrue("TimerTask.run() method should have been called at least twice ("
+ + testTask.wasRun() + ")", testTask.wasRun() >= 2);
t.cancel();
class SlowThenFastTask extends TimerTask {
@@ -1113,6 +923,7 @@
try {
Thread.sleep(200);
} catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
}
}
@@ -1133,13 +944,10 @@
// at least 9 times even when asleep
t.scheduleAtFixedRate(slowThenFastTask, d, 100);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- }
+ Thread.sleep(1000);
long lastDelta = slowThenFastTask.lastDelta();
assertTrue("Fixed Rate Schedule should catch up, but is off by "
- + lastDelta + " ms", lastDelta < 300);
+ + lastDelta + " ms", lastDelta < 300);
t.cancel();
} finally {
if (t != null)
@@ -1152,7 +960,7 @@
* let those exceptions bubble up, where they will both notify the thread's
* uncaught exception handler and terminate the timer's thread.
*/
- public void testThrowingTaskKillsTimerThread() throws InterruptedException {
+ public void testThrowingTaskKillsTimerThread() throws Exception {
final AtomicReference<Thread> threadRef = new AtomicReference<Thread>();
new Timer().schedule(new TimerTask() {
@Override public void run() {
diff --git a/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java b/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
index 31d0a12..30a1a9c 100644
--- a/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
+++ b/luni/src/test/java/tests/api/javax/net/ssl/SSLEngineTest.java
@@ -368,7 +368,7 @@
* @throws NoSuchAlgorithmException
* javax.net.ssl.SSLEngine#getDelegatedTask()
*/
- @KnownFailure("org.apache.harmony.xnet.provider.jsse.SSLEngineImpl#getDelegatedTask() throws NPE instead of returning null")
+ @KnownFailure("com.android.org.conscrypt.SSLEngineImpl#getDelegatedTask() throws NPE instead of returning null")
public void test_getDelegatedTask() throws NoSuchAlgorithmException {
SSLEngine sse = getEngine();
try {
diff --git a/luni/src/test/native/sub.mk b/luni/src/test/native/sub.mk
deleted file mode 100644
index 24dc52c..0000000
--- a/luni/src/test/native/sub.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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.
-
-LOCAL_SRC_FILES := \
- test_openssl_engine.cpp
-
-LOCAL_C_INCLUDES += \
- external/openssl/include
-
-LOCAL_SHARED_LIBRARIES += \
- libcrypto
diff --git a/support/src/test/java/libcore/java/security/StandardNames.java b/support/src/test/java/libcore/java/security/StandardNames.java
index ae25352..bb9aeda 100644
--- a/support/src/test/java/libcore/java/security/StandardNames.java
+++ b/support/src/test/java/libcore/java/security/StandardNames.java
@@ -31,6 +31,7 @@
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.crypto.spec.DHPrivateKeySpec;
@@ -99,12 +100,12 @@
PROVIDER_ALGORITHMS.put(type, algorithms);
}
assertTrue("Duplicate " + type + " " + algorithm,
- algorithms.add(algorithm.toUpperCase()));
+ algorithms.add(algorithm.toUpperCase(Locale.ROOT)));
}
private static void unprovide(String type, String algorithm) {
Set<String> algorithms = PROVIDER_ALGORITHMS.get(type);
assertNotNull(algorithms);
- assertTrue(algorithm, algorithms.remove(algorithm.toUpperCase()));
+ assertTrue(algorithm, algorithms.remove(algorithm.toUpperCase(Locale.ROOT)));
if (algorithms.isEmpty()) {
assertNotNull(PROVIDER_ALGORITHMS.remove(type));
}
@@ -212,6 +213,7 @@
provide("SecretKeyFactory", "PBEWithSHA1AndDESede");
provide("SecretKeyFactory", "PBEWithSHA1AndRC2_40");
provide("SecretKeyFactory", "PBKDF2WithHmacSHA1");
+ provide("SecretKeyFactory", "PBKDF2WithHmacSHA1And8bit");
provide("SecureRandom", "SHA1PRNG");
provide("Signature", "MD2withRSA");
provide("Signature", "MD5withRSA");
diff --git a/support/src/test/java/tests/http/MockWebServer.java b/support/src/test/java/tests/http/MockWebServer.java
index fa01380..1b776b2 100644
--- a/support/src/test/java/tests/http/MockWebServer.java
+++ b/support/src/test/java/tests/http/MockWebServer.java
@@ -36,6 +36,7 @@
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
@@ -54,7 +55,7 @@
* A scriptable web server. Callers supply canned responses and the server
* replays them upon request in sequence.
*
- * @deprecated prefer com.google.mockwebserver.MockWebServer
+ * @deprecated Use {@code com.google.mockwebserver.MockWebServer} instead.
*/
@Deprecated
public final class MockWebServer {
@@ -345,7 +346,7 @@
String header;
while (!(header = readAsciiUntilCrlf(in)).isEmpty()) {
headers.add(header);
- String lowercaseHeader = header.toLowerCase();
+ String lowercaseHeader = header.toLowerCase(Locale.ROOT);
if (contentLength == -1 && lowercaseHeader.startsWith("content-length:")) {
contentLength = Integer.parseInt(header.substring(15).trim());
}
diff --git a/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar b/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar
new file mode 100644
index 0000000..dded44f
--- /dev/null
+++ b/support/src/test/java/tests/resources/hyts_signed_authAttrs.jar
Binary files differ
diff --git a/support/src/test/java/tests/support/Support_DecimalFormat.java b/support/src/test/java/tests/support/Support_DecimalFormat.java
index 9baa4cc..89e226a 100644
--- a/support/src/test/java/tests/support/Support_DecimalFormat.java
+++ b/support/src/test/java/tests/support/Support_DecimalFormat.java
@@ -139,37 +139,26 @@
Locale us = Locale.US;
Locale tr = new Locale("de", "CH");
- if (Support_Locale.isLocaleAvailable(us)) {
- // locale dependent test, bug 1943269
+ // test number instance
+ t_Format(1, number, NumberFormat.getNumberInstance(us), getNumberVectorUS());
- // test number instance
- t_Format(1, number, NumberFormat.getNumberInstance(us),
- getNumberVectorUS());
+ // test integer instance
+ t_Format(2, number, NumberFormat.getIntegerInstance(us), getIntegerVectorUS());
- // test integer instance
- t_Format(2, number, NumberFormat.getIntegerInstance(us),
- getIntegerVectorUS());
+ // test percent instance
+ t_Format(3, number, NumberFormat.getPercentInstance(us), getPercentVectorUS());
- // test percent instance
- t_Format(3, number, NumberFormat.getPercentInstance(us),
- getPercentVectorUS());
+ // test currency instance with US Locale
+ t_Format(4, number, NumberFormat.getCurrencyInstance(us), getPositiveCurrencyVectorUS());
- // test currency instance with US Locale
- t_Format(4, number, NumberFormat.getCurrencyInstance(us),
- getPositiveCurrencyVectorUS());
+ // test negative currency instance with US Locale
+ t_Format(5, negativeNumber, NumberFormat.getCurrencyInstance(us), getNegativeCurrencyVectorUS());
- // test negative currency instance with US Locale
- t_Format(5, negativeNumber, NumberFormat.getCurrencyInstance(us),
- getNegativeCurrencyVectorUS());
+ // test multiple grouping separators
+ t_Format(6, longNumber, NumberFormat.getNumberInstance(us), getNumberVector2US());
- // test multiple grouping seperators
- t_Format(6, longNumber, NumberFormat.getNumberInstance(us),
- getNumberVector2US());
-
- // test 0
- t_Format(7, zeroNumber, NumberFormat.getNumberInstance(us),
- getZeroVector());
- }
+ // test 0
+ t_Format(7, zeroNumber, NumberFormat.getNumberInstance(us), getZeroVector());
// test permille pattern
DecimalFormat format = new DecimalFormat("###0.##\u2030");
@@ -183,15 +172,11 @@
format = new DecimalFormat("0000.0#E0");
t_Format(10, number, format, getNegativeExponentVector());
- if (Support_Locale.isLocaleAvailable(tr)) {
- // test currency instance with TR Locale
- t_Format(11, number, NumberFormat.getCurrencyInstance(tr),
- getPositiveCurrencyVectorCH());
+ // test currency instance with TR Locale
+ t_Format(11, number, NumberFormat.getCurrencyInstance(tr), getPositiveCurrencyVectorCH());
- // test negative currency instance with TR Locale
- t_Format(12, negativeNumber, NumberFormat.getCurrencyInstance(tr),
- getNegativeCurrencyVectorCH());
- }
+ // test negative currency instance with TR Locale
+ t_Format(12, negativeNumber, NumberFormat.getCurrencyInstance(tr), getNegativeCurrencyVectorCH());
}
private static Vector<FieldContainer> getNumberVectorUS() {
diff --git a/support/src/test/java/tests/support/Support_Locale.java b/support/src/test/java/tests/support/Support_Locale.java
deleted file mode 100644
index 68f01c5..0000000
--- a/support/src/test/java/tests/support/Support_Locale.java
+++ /dev/null
@@ -1,33 +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.support;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
-/**
- * Helper class for tests that rely on locale data.
- */
-public class Support_Locale {
- public static boolean isLocaleAvailable(Locale requiredLocale) {
- Set<Locale> localeSet = new HashSet<Locale>(Arrays.asList(Locale.getAvailableLocales()));
- return localeSet.contains(requiredLocale);
- }
-}
diff --git a/support/src/test/java/tests/support/Support_PortManager.java b/support/src/test/java/tests/support/Support_PortManager.java
index 9d2fd86..b68a445 100644
--- a/support/src/test/java/tests/support/Support_PortManager.java
+++ b/support/src/test/java/tests/support/Support_PortManager.java
@@ -27,7 +27,7 @@
* network port on the machine; however, it uses strange
* logic, so leave it to the OS.
*
- * @deprecated Use OS to find free ports.
+ * @deprecated Use the OS to find free ports.
*/
public class Support_PortManager {
diff --git a/xml/src/main/java/org/kxml2/io/KXmlParser.java b/xml/src/main/java/org/kxml2/io/KXmlParser.java
index 80fd8ca..84376ae 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlParser.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlParser.java
@@ -468,7 +468,7 @@
search:
while (true) {
- if (position + delimiter.length >= limit) {
+ if (position + delimiter.length > limit) {
if (start < position && returnText) {
if (result == null) {
result = new StringBuilder();
@@ -756,6 +756,9 @@
depth++;
} else if (c == ')') {
depth--;
+ } else if (c == -1) {
+ throw new XmlPullParserException(
+ "Unterminated element content spec", this, null);
}
position++;
c = peekCharacter();
@@ -857,7 +860,9 @@
position++;
// TODO: does this do escaping correctly?
String value = readValue((char) c, true, true, ValueContext.ATTRIBUTE);
- position++;
+ if (peekCharacter() == c) {
+ position++;
+ }
defineAttributeDefault(elementName, attributeName, value);
}
}
@@ -907,7 +912,9 @@
if (quote == '"' || quote == '\'') {
position++;
entityValue = readValue((char) quote, true, false, ValueContext.ENTITY_DECLARATION);
- position++;
+ if (peekCharacter() == quote) {
+ position++;
+ }
} else if (readExternalId(true, false)) {
/*
* Map external entities to the empty string. This is dishonest,
@@ -1109,7 +1116,7 @@
attributes[i + 3] = readValue(delimiter, true, throwOnResolveFailure,
ValueContext.ATTRIBUTE);
- if (delimiter != ' ') {
+ if (delimiter != ' ' && peekCharacter() == delimiter) {
position++; // end quote
}
} else if (relaxed) {
@@ -1424,12 +1431,15 @@
int c = peekCharacter();
if (c != expected) {
checkRelaxed("expected: '" + expected + "' actual: '" + ((char) c) + "'");
+ if (c == -1) {
+ return; // On EOF, don't move position beyond limit
+ }
}
position++;
}
private void read(char[] chars) throws IOException, XmlPullParserException {
- if (position + chars.length >= limit && !fillBuffer(chars.length)) {
+ if (position + chars.length > limit && !fillBuffer(chars.length)) {
checkRelaxed("expected: '" + new String(chars) + "' but was EOF");
return;
}