Merge "Removing tests that test the SqlLite API directly."
diff --git a/Android.mk b/Android.mk
index 295f2c2..fd9bcd1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -50,26 +50,4 @@
$(info ********************************************************************************)
endif
-
-#
-# "m dalvik-host" for quick minimal host build
-#
-
-.PHONY: dalvik-host
-dalvik-host: \
- dalvik \
- $(HOST_OUT)/bin/dalvikvm \
- $(HOST_OUT)/bin/dexopt \
- $(HOST_OUT)/lib/libjavacore.so \
- $(HOST_OUT)/lib/libjavacrypto.so \
- $(HOST_OUT)/lib/libjavacoretests.so \
- cacerts-host \
- core-hostdex \
- conscrypt-hostdex \
- okhttp-hostdex \
- bouncycastle-hostdex \
- apache-xml-hostdex \
- apache-harmony-tests-hostdex \
- $(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)/classes.jar
-
include $(subdir_makefiles)
diff --git a/Docs.mk b/Docs.mk
index 612b3d9..a163d1f 100644
--- a/Docs.mk
+++ b/Docs.mk
@@ -17,8 +17,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 \
+ libart/src/main/java/dalvik \
+ libart/src/main/java/java \
luni/src/main/java/android \
luni/src/main/java/java \
luni/src/main/java/javax \
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 8935b9a..c857390 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -62,7 +62,6 @@
endif
endif
-libdvm_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libdvm)
libart_core_src_files += $(common_core_src_files) $(call all-main-java-files-under,libart)
local_javac_flags=-encoding UTF-8
@@ -76,18 +75,6 @@
# Definitions to make the core library.
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(libdvm_core_src_files)
-LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_DX_FLAGS := --core-library
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := core
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-LOCAL_REQUIRED_MODULES := tzdata
-include $(BUILD_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(libart_core_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
@@ -108,7 +95,7 @@
LOCAL_SRC_FILES := $(test_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit okhttp
+LOCAL_JAVA_LIBRARIES := core-libart okhttp core-junit bouncycastle
LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support sqlite-jdbc mockwebserver nist-pkix-tests
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE := core-tests
@@ -122,7 +109,7 @@
LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := bouncycastle core core-junit
+LOCAL_JAVA_LIBRARIES := core-libart core-junit bouncycastle
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE := core-tests-support
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -135,7 +122,7 @@
LOCAL_SRC_FILES := $(call all-test-java-files-under, jsr166-tests)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core core-junit
+LOCAL_JAVA_LIBRARIES := core-libart core-junit
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE := jsr166-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -169,18 +156,6 @@
# Definitions to make the core library.
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(libdvm_core_src_files)
-LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVACFLAGS := $(local_javac_flags)
-LOCAL_DX_FLAGS := --core-library
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := core-hostdex
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
-LOCAL_REQUIRED_MODULES := tzdata-host
-include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(libart_core_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
@@ -200,7 +175,8 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(test_src_files)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
- LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex okhttp-hostdex
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVA_LIBRARIES := core-libart-hostdex okhttp-hostdex bouncycastle-hostdex core-junit-hostdex core-tests-support-hostdex
LOCAL_STATIC_JAVA_LIBRARIES := sqlite-jdbc-host mockwebserver-host nist-pkix-tests-host
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE_TAGS := optional
@@ -214,7 +190,8 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-test-java-files-under,support)
LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
- LOCAL_JAVA_LIBRARIES := bouncycastle-hostdex core-junit-hostdex
+ LOCAL_NO_STANDARD_LIBRARIES := true
+ LOCAL_JAVA_LIBRARIES := core-libart-hostdex core-junit-hostdex bouncycastle-hostdex
LOCAL_JAVACFLAGS := $(local_javac_flags)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := core-tests-support-hostdex
diff --git a/benchmarks/Android.mk b/benchmarks/Android.mk
index b91894f..c0a38a0 100644
--- a/benchmarks/Android.mk
+++ b/benchmarks/Android.mk
@@ -1,34 +1,39 @@
+# -*- mode: makefile -*-
+# 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_PATH:= $(call my-dir)
-##################################################
-include $(CLEAR_VARS)
ifeq ($(LIBCORE_SKIP_TESTS),)
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+##################################################
+include $(CLEAR_VARS)
LOCAL_MODULE := benchmarks
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- caliper-prebuilt \
- core-tests
-
-LOCAL_JAVA_LIBRARIES := \
- bouncycastle \
- conscrypt \
- core
-
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := caliper-prebuilt core-tests
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-libart conscrypt core-junit bouncycastle framework
LOCAL_MODULE_TAGS := tests
-
LOCAL_MODULE_PATH := $(PRODUCT_OUT)/data/caliperperf
-
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_JAVA_LIBRARY)
##################################################
# Prebuilt Java libraries
include $(CLEAR_VARS)
-
-LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
- caliper-prebuilt:libs/caliper.jar
-
+LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := caliper-prebuilt:libs/caliper.jar
+LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
include $(BUILD_MULTI_PREBUILT)
+
endif
diff --git a/benchmarks/src/benchmarks/regression/IcuBenchmark.java b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
index ee8270a..2aed36b 100644
--- a/benchmarks/src/benchmarks/regression/IcuBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/IcuBenchmark.java
@@ -26,7 +26,7 @@
public class IcuBenchmark extends SimpleBenchmark {
public void time_getBestDateTimePattern(int reps) throws Exception {
for (int rep = 0; rep < reps; ++rep) {
- ICU.getBestDateTimePattern("dEEEMMM", "US");
+ ICU.getBestDateTimePattern("dEEEMMM", new Locale("en", "US"));
}
}
}
diff --git a/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java b/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
index cde257b..ae6b6b6 100644
--- a/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
+++ b/benchmarks/src/benchmarks/regression/StringCaseMappingBenchmark.java
@@ -106,13 +106,13 @@
public void timeToUpperCase_ICU(int reps) {
for (int i = 0; i < reps; ++i) {
- libcore.icu.ICU.toUpperCase(s.value, Locale.US.toString());
+ libcore.icu.ICU.toUpperCase(s.value, Locale.US);
}
}
public void timeToLowerCase_ICU(int reps) {
for (int i = 0; i < reps; ++i) {
- libcore.icu.ICU.toLowerCase(s.value, Locale.US.toString());
+ libcore.icu.ICU.toLowerCase(s.value, Locale.US);
}
}
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index 6a75746..e3e1207 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -18,7 +18,6 @@
package org.apache.harmony.tests.java.net;
import java.io.IOException;
-import java.io.InterruptedIOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
@@ -29,8 +28,10 @@
import java.net.NetworkInterface;
import java.net.SocketAddress;
import java.net.SocketException;
+import java.net.SocketTimeoutException;
import java.util.ArrayList;
import java.util.Enumeration;
+import java.util.List;
public class MulticastSocketTest extends junit.framework.TestCase {
@@ -52,158 +53,124 @@
private static InetAddress GOOD_IPv6 = lookup("ff05::7:7");
private static InetAddress BAD_IPv6 = lookup("ff05::7:8");
- static class MulticastServer extends Thread {
+ private NetworkInterface loopbackInterface;
+ private NetworkInterface ipv4NetworkInterface;
+ private NetworkInterface ipv6NetworkInterface;
- public final MulticastSocket ms;
- public final byte[] rbuf = new byte[512];
- public final DatagramPacket rdp;
- private final InetAddress groupAddr;
- private final NetworkInterface groupNI;
+ @Override
+ protected void setUp() throws Exception {
+ // The loopback interface isn't actually useful for sending/receiving multicast messages
+ // but it can be used as a dummy for tests where that does not matter.
+ loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
+ assertNotNull(loopbackInterface);
+ assertTrue(loopbackInterface.isLoopback());
+ assertFalse(loopbackInterface.supportsMulticast());
- private volatile boolean running = true;
+ Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
+ assertNotNull(interfaces);
- public MulticastServer(InetAddress anAddress, int aPort) throws java.io.IOException {
- rbuf[0] = -1;
- rdp = new DatagramPacket(rbuf, rbuf.length);
- ms = new MulticastSocket(aPort);
- ms.setSoTimeout(2000);
-
- groupAddr = anAddress;
- groupNI = null;
-
- ms.joinGroup(groupAddr);
- }
-
- public MulticastServer(InetAddress anAddress, int aPort,
- NetworkInterface netInterface) throws java.io.IOException {
- rbuf[0] = -1;
- rdp = new DatagramPacket(rbuf, rbuf.length);
- ms = new MulticastSocket(aPort);
- ms.setSoTimeout(2000);
-
- groupAddr = anAddress;
- groupNI = netInterface;
-
- ms.joinGroup(new InetSocketAddress(groupAddr, ms.getLocalPort()), groupNI);
- }
-
- public void run() {
- try {
- byte[] tmpbuf = new byte[512];
- DatagramPacket tmpPack = new DatagramPacket(tmpbuf, tmpbuf.length);
-
- while (running) {
- try {
- ms.receive(tmpPack);
- System.arraycopy(tmpPack.getData(), 0, rdp.getData(), rdp.getOffset(),
- tmpPack.getLength());
- rdp.setLength(tmpPack.getLength());
- rdp.setAddress(tmpPack.getAddress());
- rdp.setPort(tmpPack.getPort());
- } catch (InterruptedIOException e) {
+ while (interfaces.hasMoreElements()
+ && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
+ NetworkInterface nextInterface = interfaces.nextElement();
+ if (willWorkForMulticast(nextInterface)) {
+ Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
+ while (addresses.hasMoreElements()) {
+ final InetAddress nextAddress = addresses.nextElement();
+ if (nextAddress instanceof Inet6Address && ipv6NetworkInterface == null) {
+ ipv6NetworkInterface = nextInterface;
+ } else if (nextAddress instanceof Inet4Address && ipv4NetworkInterface == null) {
+ ipv4NetworkInterface = nextInterface;
}
}
- } catch (java.io.IOException e) {
- fail();
- } finally {
- ms.close();
}
}
-
- public void stopServer() {
- running = false;
- try {
- ms.leaveGroup(groupAddr);
- } catch (IOException e) {
- }
- }
+ assertTrue("Test environment must have at least one interface capable of multicast for IPv4"
+ + " and IPv6",
+ ipv4NetworkInterface != null && ipv6NetworkInterface != null);
}
- private NetworkInterface loopbackInterface;
- private NetworkInterface networkInterface1;
- private NetworkInterface IPV6networkInterface1;
-
public void test_Constructor() throws IOException {
- // regression test for 497
+ // Regression test for 497.
MulticastSocket s = new MulticastSocket();
- // regression test for Harmony-1162
+ // Regression test for Harmony-1162.
assertTrue(s.getReuseAddress());
+
+ s.close();
}
public void test_ConstructorI() throws IOException {
MulticastSocket orig = new MulticastSocket();
int port = orig.getLocalPort();
orig.close();
- MulticastSocket dup = null;
- try {
- dup = new MulticastSocket(port);
- // regression test for Harmony-1162
- assertTrue(dup.getReuseAddress());
- } catch (IOException e) {
- fail("duplicate binding not allowed: " + e);
- }
- if (dup != null) {
- dup.close();
- }
+
+ MulticastSocket dup = new MulticastSocket(port);
+ // Regression test for Harmony-1162.
+ assertTrue(dup.getReuseAddress());
+ dup.close();
}
public void test_getInterface() throws Exception {
- // validate that we get the expected response when one was not set
+ // Validate that we get the expected response when one was not set.
MulticastSocket mss = new MulticastSocket(0);
- // we expect an ANY address in this case
+ // We expect an ANY address in this case.
assertTrue(mss.getInterface().isAnyLocalAddress());
- // validate that we get the expected response when we set via
- // setInterface
- Enumeration addresses = networkInterface1.getInetAddresses();
+ // Validate that we get the expected response when we set via setInterface.
+ Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
if (addresses.hasMoreElements()) {
InetAddress firstAddress = (InetAddress) addresses.nextElement();
mss.setInterface(firstAddress);
- assertEquals("getNetworkInterface did not return interface set by setInterface", firstAddress, mss.getInterface());
+ assertEquals("getNetworkInterface did not return interface set by setInterface",
+ firstAddress, mss.getInterface());
mss.close();
mss = new MulticastSocket(0);
- mss.setNetworkInterface(networkInterface1);
- assertEquals("getInterface did not return interface set by setNetworkInterface", networkInterface1, NetworkInterface.getByInetAddress(mss.getInterface()));
+ mss.setNetworkInterface(ipv4NetworkInterface);
+ assertEquals("getInterface did not return interface set by setNetworkInterface",
+ ipv4NetworkInterface, NetworkInterface.getByInetAddress(mss.getInterface()));
}
mss.close();
}
public void test_getNetworkInterface() throws IOException {
- // validate that we get the expected response when one was not set
+ // Validate that we get the expected response when one was not set.
MulticastSocket mss = new MulticastSocket(0);
NetworkInterface theInterface = mss.getNetworkInterface();
- assertTrue("network interface returned wrong network interface when not set:" + theInterface,
+ assertTrue(
+ "network interface returned wrong network interface when not set:" + theInterface,
theInterface.getInetAddresses().hasMoreElements());
- InetAddress firstAddress = (InetAddress) theInterface.getInetAddresses().nextElement();
- // validate we the first address in the network interface is the ANY address
+ InetAddress firstAddress = theInterface.getInetAddresses().nextElement();
+ // Validate we the first address in the network interface is the ANY address.
assertTrue(firstAddress.isAnyLocalAddress());
- mss.setNetworkInterface(networkInterface1);
+ mss.setNetworkInterface(ipv4NetworkInterface);
assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
- networkInterface1, mss.getNetworkInterface());
+ ipv4NetworkInterface, mss.getNetworkInterface());
mss.setNetworkInterface(loopbackInterface);
- assertEquals("getNetworkInterface did not return network interface set by second setNetworkInterface call",
+ assertEquals(
+ "getNetworkInterface did not return network interface set by second"
+ + " setNetworkInterface call",
loopbackInterface, mss.getNetworkInterface());
mss.close();
- mss = new MulticastSocket(0);
- if (IPV6networkInterface1 != null) {
- mss.setNetworkInterface(IPV6networkInterface1);
+ if (ipv6NetworkInterface != null) {
+ mss = new MulticastSocket(0);
+ mss.setNetworkInterface(ipv6NetworkInterface);
assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
- IPV6networkInterface1, mss.getNetworkInterface());
+ ipv6NetworkInterface, mss.getNetworkInterface());
+ mss.close();
}
- // validate that we get the expected response when we set via setInterface
+ // Validate that we get the expected response when we set via setInterface.
mss = new MulticastSocket(0);
- Enumeration addresses = networkInterface1.getInetAddresses();
+ Enumeration addresses = ipv4NetworkInterface.getInetAddresses();
if (addresses.hasMoreElements()) {
firstAddress = (InetAddress) addresses.nextElement();
mss.setInterface(firstAddress);
assertEquals("getNetworkInterface did not return interface set by setInterface",
- networkInterface1, mss.getNetworkInterface());
+ ipv4NetworkInterface, mss.getNetworkInterface());
}
mss.close();
}
@@ -214,12 +181,14 @@
assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
mss.setTimeToLive(220);
assertEquals("Returned incorrect 2nd TTL", 220, mss.getTimeToLive());
+ mss.close();
}
public void test_getTTL() throws Exception {
MulticastSocket mss = new MulticastSocket();
mss.setTTL((byte) 120);
assertEquals("Returned incorrect TTL", 120, mss.getTTL());
+ mss.close();
}
public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
@@ -231,19 +200,23 @@
}
private void test_joinGroupLjava_net_InetAddress(InetAddress group) throws Exception {
- MulticastServer server = new MulticastServer(group, 0);
- server.start();
- Thread.sleep(1000);
+ MulticastSocket receivingSocket = createReceivingSocket(0);
+ receivingSocket.joinGroup(group);
+
String msg = "Hello World";
- MulticastSocket mss = new MulticastSocket(server.ms.getLocalPort());
- DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
- server.ms.getLocalPort());
- mss.send(sdp, (byte) 10);
- Thread.sleep(1000);
- String receivedMessage = new String(server.rdp.getData(), 0, server.rdp.getLength());
+ MulticastSocket sendingSocket = new MulticastSocket(receivingSocket.getLocalPort());
+ InetSocketAddress groupAddress =
+ new InetSocketAddress(group, receivingSocket.getLocalPort());
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ sendingSocket.send(sdp, (byte) 10 /* ttl */);
+
+ DatagramPacket rdp = createReceiveDatagramPacket();
+ receivingSocket.receive(rdp);
+ String receivedMessage = extractMessage(rdp);
assertEquals("Group member did not recv data", msg, receivedMessage);
- mss.close();
- server.stopServer();
+
+ sendingSocket.close();
+ receivingSocket.close();
}
public void test_joinGroup_null_null() throws Exception {
@@ -276,52 +249,64 @@
mss.close();
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4() throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv4, BAD_IPv4);
+ public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+ throws Exception {
+ test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6() throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv6, BAD_IPv6);
+ public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+ throws Exception {
+ test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
- private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(InetAddress group, InetAddress group2) throws Exception {
+ private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ NetworkInterface networkInterface, InetAddress group, InetAddress group2)
+ throws Exception {
// Check that we can join a group using a null network interface.
- MulticastSocket mss = new MulticastSocket(0);
- SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
+ MulticastSocket sendingSocket = new MulticastSocket(0);
+ SocketAddress groupSockAddr = new InetSocketAddress(group, sendingSocket.getLocalPort());
+ sendingSocket.joinGroup(groupSockAddr, null);
+ sendingSocket.setTimeToLive(2);
- mss.joinGroup(groupSockAddr, null);
- mss.setTimeToLive(2);
- Thread.sleep(1000);
+ MulticastSocket receivingSocket = createReceivingSocket(0);
+ InetSocketAddress groupAddress =
+ new InetSocketAddress(group, receivingSocket.getLocalPort());
+ receivingSocket.joinGroup(groupAddress, networkInterface);
- // set up the server and join the group on networkInterface1
- MulticastServer server = new MulticastServer(group, 0, networkInterface1);
- server.start();
- Thread.sleep(1000);
String msg = "Hello World";
- DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
- server.ms.getLocalPort());
- mss.setTimeToLive(2);
- mss.send(sdp);
- Thread.sleep(1000);
- // now validate that we received the data as expected
- assertEquals("Group member did not recv data", msg, new String(server.rdp.getData(), 0, server.rdp.getLength()));
- server.stopServer();
- mss.close();
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ sendingSocket.send(sdp);
- server = new MulticastServer(group, 0, networkInterface1);
- server.start();
- Thread.sleep(1000);
+ DatagramPacket rdp = createReceiveDatagramPacket();
+ receivingSocket.receive(rdp);
+ // Now validate that we received the data as expected.
+ assertEquals("Group member did not recv data", msg, extractMessage(rdp));
+ receivingSocket.close();
+ sendingSocket.close();
- mss = new MulticastSocket(0);
- mss.setTimeToLive(10);
+ receivingSocket = createReceivingSocket(0);
+ groupAddress = new InetSocketAddress(group, receivingSocket.getLocalPort());
+ receivingSocket.joinGroup(groupAddress, networkInterface);
+
+ sendingSocket = new MulticastSocket(0);
+ sendingSocket.setTimeToLive(10);
msg = "Hello World - Different Group";
- sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2, server.ms.getLocalPort());
- mss.send(sdp);
- Thread.sleep(1000);
- assertFalse("Group member received data when sent on different group: ",
- new String(server.rdp.getData(), 0, server.rdp.getLength()).equals(msg));
- server.stopServer();
- mss.close();
+ InetSocketAddress group2Address =
+ new InetSocketAddress(group2, receivingSocket.getLocalPort());
+ sdp = createSendDatagramPacket(group2Address, msg);
+ sendingSocket.send(sdp);
+
+ rdp = createReceiveDatagramPacket();
+ try {
+ receivingSocket.receive(rdp);
+ fail("Expected timeout");
+ } catch (SocketTimeoutException expected) {
+ }
+
+ receivingSocket.close();
+ sendingSocket.close();
}
public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
@@ -329,27 +314,19 @@
// received on that interface. This test is only really useful on devices with multiple
// non-loopback interfaces.
- ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
+ List<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
while (theInterfaces.hasMoreElements()) {
NetworkInterface thisInterface = theInterfaces.nextElement();
- if (thisInterface.getInetAddresses().hasMoreElements()) {
+ // Skip interfaces that do not support multicast - there's no point in proving
+ // they cannot send / receive multicast messages.
+ if (willWorkForMulticast(thisInterface)) {
realInterfaces.add(thisInterface);
}
}
- for (int i = 0; i < realInterfaces.size(); i++) {
- NetworkInterface thisInterface = realInterfaces.get(i);
- if (!thisInterface.supportsMulticast()) {
- // Skip interfaces that do not support multicast - there's no point in proving
- // they cannot send / receive multicast messages.
- continue;
- }
-
- // get the first address on the interface
-
- // start server which is joined to the group and has
- // only asked for packets on this interface
+ for (NetworkInterface thisInterface : realInterfaces) {
+ // Find a suitable group IP and interface to use to sent packets to thisInterface.
Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
NetworkInterface sendingInterface = null;
@@ -358,57 +335,69 @@
InetAddress firstAddress = addresses.nextElement();
if (firstAddress instanceof Inet4Address) {
group = GOOD_IPv4;
- sendingInterface = networkInterface1;
+ sendingInterface = ipv4NetworkInterface;
} else {
// if this interface only seems to support IPV6 addresses
group = GOOD_IPv6;
- sendingInterface = IPV6networkInterface1;
+ sendingInterface = ipv6NetworkInterface;
}
}
- MulticastServer server = new MulticastServer(group, 0, thisInterface);
- server.start();
- Thread.sleep(1000);
+ // Create a receivingSocket which is joined to the group and has only asked for packets
+ // on thisInterface.
+ MulticastSocket receivingSocket = createReceivingSocket(0);
+ InetSocketAddress groupAddress =
+ new InetSocketAddress(group, receivingSocket.getLocalPort());
+ receivingSocket.joinGroup(groupAddress, thisInterface);
- // Now send out a package on interface networkInterface 1. We should
- // only see the packet if we send it on interface 1
- MulticastSocket mss = new MulticastSocket(0);
- mss.setNetworkInterface(sendingInterface);
- String msg = "Hello World - Again" + thisInterface.getName();
- DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
- server.ms.getLocalPort());
- mss.send(sdp);
- Thread.sleep(1000);
- if (thisInterface.equals(sendingInterface)) {
+ // Now send out a packet on sendingInterface. We should only see the packet if we send
+ // it on thisInterface.
+ MulticastSocket sendingSocket = new MulticastSocket(0);
+ sendingSocket.setNetworkInterface(sendingInterface);
+ String msg = "Hello World - Again " + thisInterface.getName();
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ sendingSocket.send(sdp);
+
+ DatagramPacket rdp = createReceiveDatagramPacket();
+ try {
+ receivingSocket.receive(rdp);
+
+ // If the packet is received....
+ assertEquals(thisInterface, sendingInterface);
assertEquals("Group member did not recv data when bound on specific interface",
- msg, new String(server.rdp.getData(), 0, server.rdp.getLength()));
- } else {
- assertFalse("Group member received data on other interface when only asked for it on one interface: ",
- new String(server.rdp.getData(), 0, server.rdp.getLength()).equals(msg));
+ msg, extractMessage(rdp));
+ } catch (SocketTimeoutException e) {
+ // If the packet was not received...
+ assertTrue(!thisInterface.equals(sendingInterface));
}
- server.stopServer();
- mss.close();
+ receivingSocket.close();
+ sendingSocket.close();
}
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4() throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(GOOD_IPv4);
+ public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
+ throws Exception {
+ test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ ipv4NetworkInterface, GOOD_IPv4);
}
- public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6() throws Exception {
- test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(GOOD_IPv6);
+ public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
+ throws Exception {
+ test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ ipv6NetworkInterface, GOOD_IPv6);
}
- private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(InetAddress group) throws Exception {
- // validate that we can join the same address on two
- // different interfaces but not on the same interface
+ private void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
+ NetworkInterface networkInterface, InetAddress group) throws Exception {
+ // Validate that we can join the same address on two different interfaces but not on the
+ // same interface.
MulticastSocket mss = new MulticastSocket(0);
SocketAddress groupSockAddr = new InetSocketAddress(group, mss.getLocalPort());
- mss.joinGroup(groupSockAddr, networkInterface1);
+ mss.joinGroup(groupSockAddr, networkInterface);
mss.joinGroup(groupSockAddr, loopbackInterface);
try {
- mss.joinGroup(groupSockAddr, networkInterface1);
+ mss.joinGroup(groupSockAddr, networkInterface);
fail("Did not get expected exception when joining for second time on same interface");
} catch (IOException e) {
}
@@ -426,9 +415,9 @@
private void test_leaveGroupLjava_net_InetAddress(InetAddress group) throws Exception {
String msg = "Hello World";
MulticastSocket mss = new MulticastSocket(0);
- DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group,
- mss.getLocalPort());
- mss.send(sdp, (byte) 10);
+ InetSocketAddress groupAddress = new InetSocketAddress(group, mss.getLocalPort());
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ mss.send(sdp, (byte) 10 /* ttl */);
try {
// Try to leave a group we didn't join.
mss.leaveGroup(group);
@@ -468,15 +457,21 @@
mss.close();
}
- public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4() throws Exception {
- test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv4, BAD_IPv4);
+ public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
+ throws Exception {
+ test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
}
- public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6() throws Exception {
- test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(GOOD_IPv6, BAD_IPv6);
+ public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
+ throws Exception {
+ test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
}
- private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(InetAddress group, InetAddress group2) throws Exception {
+ private void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
+ NetworkInterface networkInterface, InetAddress group, InetAddress group2)
+ throws Exception {
SocketAddress groupSockAddr = null;
SocketAddress groupSockAddr2 = null;
@@ -491,20 +486,20 @@
}
groupSockAddr2 = new InetSocketAddress(group2, mss.getLocalPort());
- mss.joinGroup(groupSockAddr, networkInterface1);
+ mss.joinGroup(groupSockAddr, networkInterface);
try {
- mss.leaveGroup(groupSockAddr2, networkInterface1);
+ mss.leaveGroup(groupSockAddr2, networkInterface);
fail("Did not get exception when trying to leave group that was never joined");
} catch (IOException expected) {
}
- mss.leaveGroup(groupSockAddr, networkInterface1);
+ mss.leaveGroup(groupSockAddr, networkInterface);
- mss.joinGroup(groupSockAddr, networkInterface1);
+ mss.joinGroup(groupSockAddr, networkInterface);
try {
mss.leaveGroup(groupSockAddr, loopbackInterface);
fail("Did not get exception when trying to leave group on wrong interface " +
- "joined on [" + networkInterface1 + "] left on [" + loopbackInterface + "]");
+ "joined on [" + networkInterface + "] left on [" + loopbackInterface + "]");
} catch (IOException expected) {
}
}
@@ -519,31 +514,36 @@
private void test_sendLjava_net_DatagramPacketB(InetAddress group) throws Exception {
String msg = "Hello World";
- MulticastSocket mss = new MulticastSocket(0);
- MulticastServer server = new MulticastServer(group, mss.getLocalPort());
- server.start();
- Thread.sleep(200);
- DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg.length(), group, mss.getLocalPort());
- mss.send(sdp, (byte) 10);
- Thread.sleep(1000);
- mss.close();
- byte[] data = server.rdp.getData();
- int length = server.rdp.getLength();
- assertEquals("Failed to send data. Received " + length, msg, new String(data, 0, length));
- server.stopServer();
+ MulticastSocket sendingSocket = new MulticastSocket(0);
+ MulticastSocket receivingSocket = createReceivingSocket(sendingSocket.getLocalPort());
+ receivingSocket.joinGroup(group);
+
+ InetSocketAddress groupAddress = new InetSocketAddress(group, sendingSocket.getLocalPort());
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ sendingSocket.send(sdp, (byte) 10 /* ttl */);
+ sendingSocket.close();
+
+ DatagramPacket rdp = createReceiveDatagramPacket();
+ receivingSocket.receive(rdp);
+ String receivedMessage = extractMessage(rdp);
+ assertEquals("Failed to send data. Received " + rdp.getLength(), msg, receivedMessage);
+ receivingSocket.close();
}
public void test_setInterfaceLjava_net_InetAddress() throws Exception {
MulticastSocket mss = new MulticastSocket();
mss.setInterface(InetAddress.getLocalHost());
InetAddress theInterface = mss.getInterface();
- // under IPV6 we are not guarrenteed to get the same address back as
- // the address, all we should be guaranteed is that we get an
- // address on the same interface
+ // Under IPV6 we are not guaranteed to get the same address back as the address that was
+ // set, all we should be guaranteed is that we get an address on the same interface.
if (theInterface instanceof Inet6Address) {
- assertTrue("Failed to return correct interface IPV6", NetworkInterface.getByInetAddress(mss.getInterface()).equals(NetworkInterface.getByInetAddress(theInterface)));
+ assertEquals("Failed to return correct interface IPV6",
+ NetworkInterface.getByInetAddress(mss.getInterface()),
+ NetworkInterface.getByInetAddress(theInterface));
} else {
- assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() + " excpeted: " + InetAddress.getLocalHost(), mss.getInterface().equals(InetAddress.getLocalHost()));
+ assertTrue("Failed to return correct interface IPV4 got:" + mss.getInterface() +
+ " expected: " + InetAddress.getLocalHost(),
+ mss.getInterface().equals(InetAddress.getLocalHost()));
}
mss.close();
}
@@ -556,7 +556,7 @@
test_setInterface_unbound_address(GOOD_IPv6);
}
- // Regression test for Harmony-2410
+ // Regression test for Harmony-2410.
private void test_setInterface_unbound_address(InetAddress address) throws Exception {
MulticastSocket mss = new MulticastSocket();
try {
@@ -568,7 +568,7 @@
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
- // validate that null interface is handled ok
+ // Validate that null interface is handled ok.
MulticastSocket mss = new MulticastSocket();
try {
mss.setNetworkInterface(null);
@@ -579,10 +579,11 @@
}
public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
- // validate that we can get and set the interface
+ // Validate that we can get and set the interface.
MulticastSocket mss = new MulticastSocket();
- mss.setNetworkInterface(networkInterface1);
- assertEquals("Interface did not seem to be set by setNeworkInterface", networkInterface1, mss.getNetworkInterface());
+ mss.setNetworkInterface(ipv4NetworkInterface);
+ assertEquals("Interface did not seem to be set by setNeworkInterface",
+ ipv4NetworkInterface, mss.getNetworkInterface());
mss.close();
}
@@ -594,35 +595,35 @@
test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
}
- private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group) throws IOException, InterruptedException {
- // set up the server and join the group
+ private void test_setNetworkInterfaceLjava_net_NetworkInterface(InetAddress group)
+ throws IOException, InterruptedException {
+ // Set up the receiving socket and join the group.
Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
while (theInterfaces.hasMoreElements()) {
NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
if (thisInterface.getInetAddresses().hasMoreElements() && thisInterface.isUp()) {
if ((!(thisInterface.getInetAddresses().nextElement()).isLoopbackAddress())) {
- MulticastServer server = new MulticastServer(group, 0);
- server.start();
- // give the server some time to start up
- Thread.sleep(1000);
+ MulticastSocket receivingSocket = createReceivingSocket(0);
+ InetSocketAddress groupAddress =
+ new InetSocketAddress(group, receivingSocket.getLocalPort());
+ receivingSocket.joinGroup(groupAddress, thisInterface);
- // Send the packets on a particular interface. The
- // source address in the received packet
- // should be one of the addresses for the interface
- // set
- MulticastSocket mss = new MulticastSocket(0);
- mss.setNetworkInterface(thisInterface);
+ // Send the packets on a particular interface. The source address in the
+ // received packet should be one of the addresses for the interface set.
+ MulticastSocket sendingSocket = new MulticastSocket(0);
+ sendingSocket.setNetworkInterface(thisInterface);
String msg = thisInterface.getName();
- byte theBytes[] = msg.getBytes();
- DatagramPacket sdp = new DatagramPacket(theBytes, theBytes.length, group,
- server.ms.getLocalPort());
- mss.send(sdp);
- Thread.sleep(1000);
- String receivedMessage = new String(server.rdp.getData(), 0, server.rdp.getLength());
- assertEquals("Group member did not recv data sent on a specific interface", msg, receivedMessage);
- // stop the server
- server.stopServer();
- mss.close();
+ DatagramPacket sdp = createSendDatagramPacket(groupAddress, msg);
+ sendingSocket.send(sdp);
+
+ DatagramPacket rdp = createReceiveDatagramPacket();
+ receivingSocket.receive(rdp);
+ String receivedMessage = extractMessage(rdp);
+ assertEquals("Group member did not recv data sent on a specific interface",
+ msg, receivedMessage);
+ // Stop the server.
+ receivingSocket.close();
+ sendingSocket.close();
}
}
}
@@ -651,24 +652,28 @@
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
+
ms = new MulticastSocket(0);
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
+
ms = new MulticastSocket(0);
assertTrue("should be bound", ms.isBound() && !ms.isClosed() && !ms.isConnected());
ms.close();
assertTrue("should be closed", ms.isClosed());
+
try {
- ms = new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
+ new MulticastSocket(new InetSocketAddress("unresolvedname", 31415));
fail();
} catch (IOException expected) {
}
- // regression test for Harmony-1162
+ // Regression test for Harmony-1162.
InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
MulticastSocket s = new MulticastSocket(addr);
assertTrue(s.getReuseAddress());
+ s.close();
}
public void test_getLoopbackMode() throws Exception {
@@ -699,129 +704,69 @@
}
private void test_setLoopbackModeSendReceive(InetAddress group) throws IOException {
+ // Test send receive.
final String message = "Hello, world!";
- // test send receive
MulticastSocket socket = new MulticastSocket(0);
socket.setLoopbackMode(false); // false indicates doing loop back
socket.joinGroup(group);
- // send the datagram
- byte[] sendData = message.getBytes();
- DatagramPacket sendDatagram = new DatagramPacket(sendData, 0, sendData.length,
- new InetSocketAddress(group, socket.getLocalPort()));
+ // Send the datagram.
+ InetSocketAddress groupAddress = new InetSocketAddress(group, socket.getLocalPort());
+ DatagramPacket sendDatagram = createSendDatagramPacket(groupAddress, message);
socket.send(sendDatagram);
- // receive the datagram
- byte[] recvData = new byte[100];
- DatagramPacket recvDatagram = new DatagramPacket(recvData, recvData.length);
- socket.setSoTimeout(5000); // prevent eternal block in
+ // Receive the datagram.
+ DatagramPacket recvDatagram = createReceiveDatagramPacket();
+ socket.setSoTimeout(5000); // Prevent eternal block in.
socket.receive(recvDatagram);
- String recvMessage = new String(recvData, 0, recvDatagram.getLength());
+ String recvMessage = extractMessage(recvDatagram);
assertEquals(message, recvMessage);
socket.close();
}
public void test_setReuseAddressZ() throws Exception {
- // test case were we set it to false
- MulticastSocket theSocket1 = null;
- MulticastSocket theSocket2 = null;
+ // Test case were we to set ReuseAddress to false.
+ MulticastSocket theSocket1 = new MulticastSocket(null);
+ theSocket1.setReuseAddress(false);
+
+ MulticastSocket theSocket2 = new MulticastSocket(null);
+ theSocket2.setReuseAddress(false);
+
+ InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
+ theSocket1.bind(addr);
+ addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
try {
- theSocket1 = new MulticastSocket(null);
- theSocket2 = new MulticastSocket(null);
- theSocket1.setReuseAddress(false);
- theSocket2.setReuseAddress(false);
- InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
- theSocket1.bind(addr);
- addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
theSocket2.bind(addr);
- fail("No exception when trying to connect to do duplicate socket bind with re-useaddr set to false");
+ fail("No exception when trying to connect to do duplicate socket bind with re-useaddr"
+ + " set to false");
} catch (BindException expected) {
}
- if (theSocket1 != null) {
- theSocket1.close();
- }
- if (theSocket2 != null) {
- theSocket2.close();
- }
+ theSocket1.close();
+ theSocket2.close();
- // test case were we set it to true
+ // Test case were we set it to true.
theSocket1 = new MulticastSocket(null);
theSocket2 = new MulticastSocket(null);
theSocket1.setReuseAddress(true);
theSocket2.setReuseAddress(true);
- InetSocketAddress addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
+ addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
theSocket1.bind(addr);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
theSocket2.bind(addr);
- if (theSocket1 != null) {
- theSocket1.close();
- }
- if (theSocket2 != null) {
- theSocket2.close();
- }
+ theSocket1.close();
+ theSocket2.close();
- // test the default case which we expect to be
- // the same on all platforms
+ // Test the default case which we expect to be the same on all platforms.
theSocket1 = new MulticastSocket(null);
theSocket2 = new MulticastSocket(null);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), 0);
theSocket1.bind(addr);
addr = new InetSocketAddress(Inet4Address.getLocalHost(), theSocket1.getLocalPort());
theSocket2.bind(addr);
- if (theSocket1 != null) {
- theSocket1.close();
- }
- if (theSocket2 != null) {
- theSocket2.close();
- }
- }
-
- @Override
- protected void setUp() throws Exception {
- // The loopback interface isn't actually useful for sending/receiving multicast messages
- // but it can be used as a dummy for tests where that does not matter.
- loopbackInterface = NetworkInterface.getByInetAddress(InetAddress.getLoopbackAddress());
- assertNotNull(loopbackInterface);
- assertTrue(loopbackInterface.isLoopback());
- assertFalse(loopbackInterface.supportsMulticast());
-
- Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
-
- // only consider interfaces that have addresses associated with them.
- // Otherwise tests don't work so well
- if (interfaces != null) {
- boolean atLeastOneInterface = false;
- while (interfaces.hasMoreElements() && (atLeastOneInterface == false)) {
- networkInterface1 = interfaces.nextElement();
- if (willWorkForMulticast(networkInterface1)) {
- atLeastOneInterface = true;
- }
- }
-
- assertTrue("Test environment must have at least one environment capable of multicast",
- atLeastOneInterface);
-
- // Find the first multicast-compatible interface that supports IPV6 if one exists
- interfaces = NetworkInterface.getNetworkInterfaces();
-
- boolean found = false;
- while (interfaces.hasMoreElements() && !found) {
- NetworkInterface nextInterface = interfaces.nextElement();
- if (willWorkForMulticast(nextInterface)) {
- Enumeration<InetAddress> addresses = nextInterface.getInetAddresses();
- while (addresses.hasMoreElements()) {
- final InetAddress nextAddress = addresses.nextElement();
- if (nextAddress instanceof Inet6Address) {
- IPV6networkInterface1 = nextInterface;
- found = true;
- break;
- }
- }
- }
- }
- }
+ theSocket1.close();
+ theSocket2.close();
}
private static boolean willWorkForMulticast(NetworkInterface iface) throws IOException {
@@ -831,4 +776,26 @@
&& !iface.isLoopback() && iface.supportsMulticast()
&& iface.getInetAddresses().hasMoreElements();
}
+
+ private static MulticastSocket createReceivingSocket(int aPort) throws IOException {
+ MulticastSocket ms = new MulticastSocket(aPort);
+ ms.setSoTimeout(2000);
+ return ms;
+ }
+
+ private static DatagramPacket createReceiveDatagramPacket() {
+ byte[] rbuf = new byte[512];
+ return new DatagramPacket(rbuf, rbuf.length);
+ }
+
+ private static DatagramPacket createSendDatagramPacket(
+ InetSocketAddress groupAndPort, String msg) {
+ return new DatagramPacket(
+ msg.getBytes(), msg.length(), groupAndPort.getAddress(), groupAndPort.getPort());
+ }
+
+ private static String extractMessage(DatagramPacket rdp) {
+ return new String(rdp.getData(), 0, rdp.getLength());
+ }
+
}
diff --git a/include/ScopedIcuLocale.h b/include/ScopedIcuLocale.h
new file mode 100644
index 0000000..2109e03
--- /dev/null
+++ b/include/ScopedIcuLocale.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 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_ICU_LOCALE_H_included
+#define SCOPED_ICU_LOCALE_H_included
+
+#include "JNIHelp.h"
+#include "ScopedUtfChars.h"
+#include "unicode/locid.h"
+
+class ScopedIcuLocale {
+ public:
+ ScopedIcuLocale(JNIEnv* env, jstring javaLocaleName) : mEnv(env) {
+ mLocale.setToBogus();
+
+ if (javaLocaleName == NULL) {
+ jniThrowNullPointerException(mEnv, "javaLocaleName == null");
+ return;
+ }
+
+ const ScopedUtfChars localeName(env, javaLocaleName);
+ if (localeName.c_str() == NULL) {
+ return;
+ }
+
+ mLocale = Locale::createFromName(localeName.c_str());
+ }
+
+ ~ScopedIcuLocale() {
+ }
+
+ bool valid() const {
+ return !mLocale.isBogus();
+ }
+
+ Locale& locale() {
+ return mLocale;
+ }
+
+ private:
+ JNIEnv* const mEnv;
+ Locale mLocale;
+
+ // Disallow copy and assignment.
+ ScopedIcuLocale(const ScopedIcuLocale&);
+ void operator=(const ScopedIcuLocale&);
+};
+
+#endif // SCOPED_ICU_LOCALE_H_included
diff --git a/libart/src/main/java/java/lang/reflect/AbstractMethod.java b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
index ff52b41..df6b2ce 100644
--- a/libart/src/main/java/java/lang/reflect/AbstractMethod.java
+++ b/libart/src/main/java/java/lang/reflect/AbstractMethod.java
@@ -135,7 +135,7 @@
*
* @return the parameter types
*/
- public Class<?>[] getParameterTypes() {
+ Class<?>[] getParameterTypes() {
return artMethod.getParameterTypes();
}
diff --git a/libart/src/main/java/java/lang/reflect/Constructor.java b/libart/src/main/java/java/lang/reflect/Constructor.java
index b1efe06..2eb12b0 100644
--- a/libart/src/main/java/java/lang/reflect/Constructor.java
+++ b/libart/src/main/java/java/lang/reflect/Constructor.java
@@ -111,7 +111,7 @@
* parameter types of this constructor. If the constructor was declared with
* no parameters, an empty array will be returned.
*/
- public Class<?>[] getParameterTypes() {
+ @Override public Class<?>[] getParameterTypes() {
return super.getParameterTypes();
}
diff --git a/libdvm/src/main/java/dalvik/system/VMRuntime.java b/libdvm/src/main/java/dalvik/system/VMRuntime.java
deleted file mode 100644
index 1d58d8d..0000000
--- a/libdvm/src/main/java/dalvik/system/VMRuntime.java
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dalvik.system;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Provides an interface to VM-global, Dalvik-specific features.
- * An application cannot create its own Runtime instance, and must obtain
- * one from the getRuntime method.
- *
- * @hide
- */
-public final class VMRuntime {
-
- /**
- * Holds the VMRuntime singleton.
- */
- private static final VMRuntime THE_ONE = new VMRuntime();
-
- private static final Map<String, String> ABI_TO_INSTRUCTION_SET_MAP
- = new HashMap<String, String>();
- static {
- ABI_TO_INSTRUCTION_SET_MAP.put("armeabi", "arm");
- ABI_TO_INSTRUCTION_SET_MAP.put("armeabi-v7a", "arm");
- ABI_TO_INSTRUCTION_SET_MAP.put("mips", "mips");
- ABI_TO_INSTRUCTION_SET_MAP.put("x86", "x86");
- }
-
- private int targetSdkVersion;
-
- /**
- * Prevents this class from being instantiated.
- */
- private VMRuntime() {
- }
-
- /**
- * Returns the object that represents the VM instance's Dalvik-specific
- * runtime environment.
- *
- * @return the runtime object
- */
- public static VMRuntime getRuntime() {
- return THE_ONE;
- }
-
- /**
- * Returns a copy of the VM's command-line property settings.
- * These are in the form "name=value" rather than "-Dname=value".
- */
- public native String[] properties();
-
- /**
- * Returns the VM's boot class path.
- */
- public native String bootClassPath();
-
- /**
- * Returns the VM's class path.
- */
- public native String classPath();
-
- /**
- * Returns the VM's version.
- */
- public native String vmVersion();
-
- /**
- * Returns the name of the shared library providing the VM implementation.
- */
- public native String vmLibrary();
-
- /**
- * Returns the VM's instruction set.
- */
- public String vmInstructionSet() {
- return "";
- }
-
- /**
- * Returns whether the VM is running in 64-bit mode.
- */
- public boolean is64Bit() {
- return false;
- }
-
- /**
- * Returns whether the VM is running with JNI checking enabled.
- */
- public native boolean isCheckJniEnabled();
-
- /**
- * Gets the current ideal heap utilization, represented as a number
- * between zero and one. After a GC happens, the Dalvik heap may
- * be resized so that (size of live objects) / (size of heap) is
- * equal to this number.
- *
- * @return the current ideal heap utilization
- */
- public native float getTargetHeapUtilization();
-
- /**
- * Sets the current ideal heap utilization, represented as a number
- * between zero and one. After a GC happens, the Dalvik heap may
- * be resized so that (size of live objects) / (size of heap) is
- * equal to this number.
- *
- * <p>This is only a hint to the garbage collector and may be ignored.
- *
- * @param newTarget the new suggested ideal heap utilization.
- * This value may be adjusted internally.
- * @return the previous ideal heap utilization
- * @throws IllegalArgumentException if newTarget is <= 0.0 or >= 1.0
- */
- public float setTargetHeapUtilization(float newTarget) {
- if (newTarget <= 0.0f || newTarget >= 1.0f) {
- throw new IllegalArgumentException(newTarget +
- " out of range (0,1)");
- }
- /* Synchronize to make sure that only one thread gets
- * a given "old" value if both update at the same time.
- * Allows for reliable save-and-restore semantics.
- */
- synchronized (this) {
- float oldTarget = getTargetHeapUtilization();
- nativeSetTargetHeapUtilization(newTarget);
- return oldTarget;
- }
- }
-
- /**
- * Sets the target SDK version. Should only be called before the
- * app starts to run, because it may change the VM's behavior in
- * dangerous ways. Use 0 to mean "current" (since callers won't
- * necessarily know the actual current SDK version, and the
- * allocated version numbers start at 1), and 10000 to mean
- * CUR_DEVELOPMENT.
- */
- public synchronized void setTargetSdkVersion(int targetSdkVersion) {
- this.targetSdkVersion = targetSdkVersion;
- setTargetSdkVersionNative(this.targetSdkVersion);
- }
-
- /**
- * Gets the target SDK version. See {@link #setTargetSdkVersion} for
- * special values.
- */
- public synchronized int getTargetSdkVersion() {
- return targetSdkVersion;
- }
-
- private native void setTargetSdkVersionNative(int targetSdkVersion);
-
- /**
- * This method exists for binary compatibility. It was part of a
- * heap sizing API which was removed in Android 3.0 (Honeycomb).
- */
- @Deprecated
- public long getMinimumHeapSize() {
- return 0;
- }
-
- /**
- * This method exists for binary compatibility. It was part of a
- * heap sizing API which was removed in Android 3.0 (Honeycomb).
- */
- @Deprecated
- public long setMinimumHeapSize(long size) {
- return 0;
- }
-
- /**
- * This method exists for binary compatibility. It used to
- * perform a garbage collection that cleared SoftReferences.
- */
- @Deprecated
- public void gcSoftReferences() {}
-
- /**
- * This method exists for binary compatibility. It is equivalent
- * to {@link System#runFinalization}.
- */
- @Deprecated
- public void runFinalizationSync() {
- System.runFinalization();
- }
-
- /**
- * Implements setTargetHeapUtilization().
- *
- * @param newTarget the new suggested ideal heap utilization.
- * This value may be adjusted internally.
- */
- private native void nativeSetTargetHeapUtilization(float newTarget);
-
- /**
- * This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Android 3.0 (Honeycomb).
- */
- @Deprecated
- public boolean trackExternalAllocation(long size) {
- return true;
- }
-
- /**
- * This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Android 3.0 (Honeycomb).
- */
- @Deprecated
- public void trackExternalFree(long size) {}
-
- /**
- * This method exists for binary compatibility. It was part of
- * the external allocation API which was removed in Android 3.0 (Honeycomb).
- */
- @Deprecated
- public long getExternalBytesAllocated() {
- return 0;
- }
-
- /**
- * Tells the VM to enable the JIT compiler. If the VM does not have a JIT
- * implementation, calling this method should have no effect.
- */
- public native void startJitCompilation();
-
- /**
- * Tells the VM to disable the JIT compiler. If the VM does not have a JIT
- * implementation, calling this method should have no effect.
- */
- public native void disableJitCompilation();
-
- /**
- * Returns an array allocated in an area of the Java heap where it will never be moved.
- * This is used to implement native allocations on the Java heap, such as DirectByteBuffers
- * and Bitmaps.
- */
- public native Object newNonMovableArray(Class<?> componentType, int length);
-
- /**
- * Returns an array of at least minLength, but potentially larger. The increased size comes from
- * avoiding any padding after the array. The amount of padding varies depending on the
- * componentType and the memory allocator implementation.
- */
- public Object newUnpaddedArray(Class<?> componentType, int minLength) {
- // Dalvik has 32bit pointers, the array header is 16bytes plus 4bytes for dlmalloc,
- // allocations are 8byte aligned so having 4bytes of array data avoids padding.
- if (!componentType.isPrimitive()) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return java.lang.reflect.Array.newInstance(componentType, size);
- } else if (componentType == char.class) {
- int bytes = 20 + (2 * minLength);
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes / 2;
- return new char[size];
- } else if (componentType == int.class) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return new int[size];
- } else if (componentType == byte.class) {
- int bytes = 20 + minLength;
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes;
- return new byte[size];
- } else if (componentType == boolean.class) {
- int bytes = 20 + minLength;
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes;
- return new boolean[size];
- } else if (componentType == short.class) {
- int bytes = 20 + (2 * minLength);
- int alignedUpBytes = (bytes + 7) & -8;
- int dataBytes = alignedUpBytes - 20;
- int size = dataBytes / 2;
- return new short[size];
- } else if (componentType == float.class) {
- int size = ((minLength & 1) == 0) ? minLength + 1 : minLength;
- return new float[size];
- } else if (componentType == long.class) {
- return new long[minLength];
- } else if (componentType == double.class) {
- return new double[minLength];
- } else {
- assert componentType == void.class;
- throw new IllegalArgumentException("Can't allocate an array of void");
- }
- }
-
- /**
- * Returns the address of array[0]. This differs from using JNI in that JNI might lie and
- * give you the address of a copy of the array when in forcecopy mode.
- */
- public native long addressOf(Object array);
-
- /**
- * Removes any growth limits, allowing the application to allocate
- * up to the maximum heap size.
- */
- public native void clearGrowthLimit();
-
- /**
- * Returns true if either a Java debugger or native debugger is active.
- */
- public native boolean isDebuggerActive();
-
- /**
- * Registers a native allocation so that the heap knows about it and performs GC as required.
- * If the number of native allocated bytes exceeds the native allocation watermark, the
- * function requests a concurrent GC. If the native bytes allocated exceeds a second higher
- * watermark, it is determined that the application is registering native allocations at an
- * unusually high rate and a GC is performed inside of the function to prevent memory usage
- * from excessively increasing.
- */
- public native void registerNativeAllocation(int bytes);
-
- /**
- * Registers a native free by reducing the number of native bytes accounted for.
- */
- public native void registerNativeFree(int bytes);
-
- /**
- * Let the heap know of the new process state. This can change allocation and garbage collection
- * behavior regarding trimming and compaction.
- */
- public native void updateProcessState(int state);
-
- /**
- * Fill in dex caches with classes, fields, and methods that are
- * already loaded. Typically used after Zygote preloading.
- */
- public native void preloadDexCaches();
-
- /**
- * Register application info
- */
- public static void registerAppInfo(String appDir, String processName, String pkgname) {
- // Nothing to do in dalvik.
- }
-
- /**
- * Returns the runtime instruction set corresponding to a given ABI. Multiple
- * compatible ABIs might map to the same instruction set. For example
- * {@code armeabi-v7a} and {@code armeabi} might map to the instruction set {@code arm}.
- *
- * This influences the compilation of the applications classes.
- */
- public static String getInstructionSet(String abi) {
- final String instructionSet = ABI_TO_INSTRUCTION_SET_MAP.get(abi);
- if (instructionSet == null) {
- throw new IllegalArgumentException("Unsupported ABI: " + abi);
- }
-
- return instructionSet;
- }
-}
diff --git a/libdvm/src/main/java/dalvik/system/VMStack.java b/libdvm/src/main/java/dalvik/system/VMStack.java
deleted file mode 100644
index bae1829..0000000
--- a/libdvm/src/main/java/dalvik/system/VMStack.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package dalvik.system;
-
-/**
- * Provides a limited interface to the Dalvik VM stack. This class is mostly
- * used for implementing security checks.
- *
- * @hide
- */
-public final class VMStack {
- /**
- * Returns the defining class loader of the caller's caller.
- *
- * @return the requested class loader, or {@code null} if this is the
- * bootstrap class loader.
- */
- native public static ClassLoader getCallingClassLoader();
-
- /**
- * Returns the class of the caller's caller's caller.
- *
- * @return the requested class, or {@code null}.
- */
- native public static Class<?> getStackClass2();
-
- /**
- * Creates an array of classes from the methods at the top of the stack.
- * We continue until we reach the bottom of the stack or exceed the
- * specified maximum depth.
- * <p>
- * The topmost stack frame (this method) and the one above that (the
- * caller) are excluded from the array. Frames with java.lang.reflect
- * classes are skipped over.
- * <p>
- * The classes in the array are the defining classes of the methods.
- * <p>
- * This is similar to Harmony's VMStack.getClasses, except that this
- * implementation doesn't have a concept of "privileged" frames.
- *
- * @param maxDepth
- * maximum number of classes to return, or -1 for all
- * @return an array with classes for the most-recent methods on the stack
- */
- 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
- * thread of interest
- * @return an array of stack trace elements, or null if the thread
- * doesn't have a stack trace (e.g. because it exited)
- */
- native public static StackTraceElement[] getThreadStackTrace(Thread t);
-
- /**
- * Retrieves a partial stack trace from the specified thread into
- * the provided array.
- *
- * @param t
- * thread of interest
- * @param stackTraceElements
- * preallocated array for use when only the top of stack is
- * desired. Unused elements will be filled with null values.
- * @return the number of elements filled
- */
- native public static int fillStackTraceElements(Thread t,
- StackTraceElement[] stackTraceElements);
-}
diff --git a/libdvm/src/main/java/java/lang/Class.java b/libdvm/src/main/java/java/lang/Class.java
deleted file mode 100644
index af6278d..0000000
--- a/libdvm/src/main/java/java/lang/Class.java
+++ /dev/null
@@ -1,1354 +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.
- */
-/*
- * Copyright (C) 2006-2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import com.android.dex.Dex;
-import dalvik.system.VMStack;
-import java.io.InputStream;
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Inherited;
-import java.lang.reflect.AnnotatedElement;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.GenericDeclaration;
-import java.lang.reflect.Member;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Type;
-import java.lang.reflect.TypeVariable;
-import java.net.URL;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.AnnotationAccess;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.InternalNames;
-import libcore.reflect.Types;
-import libcore.util.BasicLruCache;
-import libcore.util.CollectionUtils;
-import libcore.util.EmptyArray;
-
-/**
- * The in-memory representation of a Java class. This representation serves as
- * the starting point for querying class-related information, a process usually
- * called "reflection". There are basically three types of {@code Class}
- * instances: those representing real classes and interfaces, those representing
- * primitive types, and those representing array classes.
- *
- * <h4>Class instances representing object types (classes or interfaces)</h4>
- * <p>
- * These represent an ordinary class or interface as found in the class
- * hierarchy. The name associated with these {@code Class} instances is simply
- * the fully qualified class name of the class or interface that it represents.
- * In addition to this human-readable name, each class is also associated by a
- * so-called <em>signature</em>, which is the letter "L", followed by the
- * class name and a semicolon (";"). The signature is what the runtime system
- * uses internally for identifying the class (for example in a DEX file).
- * </p>
- * <h4>Classes representing primitive types</h4>
- * <p>
- * These represent the standard Java primitive types and hence share their
- * names (for example "int" for the {@code int} primitive type). Although it is
- * not possible to create new instances based on these {@code Class} instances,
- * they are still useful for providing reflection information, and as the
- * component type of array classes. There is one {@code Class} instance for each
- * primitive type, and their signatures are:
- * </p>
- * <ul>
- * <li>{@code B} representing the {@code byte} primitive type</li>
- * <li>{@code S} representing the {@code short} primitive type</li>
- * <li>{@code I} representing the {@code int} primitive type</li>
- * <li>{@code J} representing the {@code long} primitive type</li>
- * <li>{@code F} representing the {@code float} primitive type</li>
- * <li>{@code D} representing the {@code double} primitive type</li>
- * <li>{@code C} representing the {@code char} primitive type</li>
- * <li>{@code Z} representing the {@code boolean} primitive type</li>
- * <li>{@code V} representing void function return values</li>
- * </ul>
- * <p>
- * <h4>Classes representing array classes</h4>
- * <p>
- * These represent the classes of Java arrays. There is one such {@code Class}
- * instance per combination of array leaf component type and arity (number of
- * dimensions). In this case, the name associated with the {@code Class}
- * consists of one or more left square brackets (one per dimension in the array)
- * followed by the signature of the class representing the leaf component type,
- * which can be either an object type or a primitive type. The signature of a
- * {@code Class} representing an array type is the same as its name. Examples
- * of array class signatures are:
- * </p>
- * <ul>
- * <li>{@code [I} representing the {@code int[]} type</li>
- * <li>{@code [Ljava/lang/String;} representing the {@code String[]} type</li>
- * <li>{@code [[[C} representing the {@code char[][][]} type (three dimensions!)</li>
- * </ul>
- */
-public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {
-
- private static final long serialVersionUID = 3206093459760846163L;
-
- /**
- * Class def index from dex file. An index of -1 indicates that there is no class definition,
- * for example for an array type.
- */
- private transient int dexClassDefIndex;
-
- /** The type index of this class within the dex file that defines it. */
- private transient int dexTypeIndex;
-
- /**
- * Have we computed the type and class def indices? Volatile to avoid double check locking bugs.
- */
- private transient volatile boolean dexIndicesInitialized;
-
- /**
- * Lazily computed name of this class; always prefer calling getName().
- */
- private transient String name;
-
- private 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();
-
- /** Lazily compute indices in to Dex */
- private synchronized void computeDexIndices() {
- if (!dexIndicesInitialized) {
- Dex dex = getDex();
- dexTypeIndex = dex.findTypeIndex(InternalNames.getInternalName(this));
- if (dexTypeIndex < 0) {
- dexTypeIndex = -1;
- dexClassDefIndex = -1;
- } else {
- dexClassDefIndex = dex.findClassDefIndexFromTypeIndex(dexTypeIndex);
- }
- dexIndicesInitialized = true;
- }
- }
-
- /**
- * The class def of this class in its own Dex, or -1 if there is no class def.
- *
- * @hide
- */
- public int getDexClassDefIndex() {
- if (!dexIndicesInitialized) {
- computeDexIndices();
- }
- return dexClassDefIndex;
- }
-
- /**
- * The type index of this class in its own Dex, or -1 if it is unknown. If a class is referenced
- * by multiple Dex files, it will have a different type index in each. Dex files support 65534
- * type indices, with 65535 representing no index.
- *
- * @hide
- */
- public int getDexTypeIndex() {
- if (!dexIndicesInitialized) {
- computeDexIndices();
- }
- return dexTypeIndex;
- }
-
- /**
- * Returns a {@code Class} object which represents the class with the
- * given name. The name should be the name of a non-primitive class, as described in
- * the {@link Class class definition}.
- * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
- *
- * <p>If the class has not yet been loaded, it is loaded and initialized
- * first. This is done through either the class loader of the calling class
- * or one of its parent class loaders. It is possible that a static initializer is run as
- * a result of this call.
- *
- * @throws ClassNotFoundException
- * if the requested class can not be found.
- * @throws LinkageError
- * if an error occurs during linkage
- * @throws ExceptionInInitializerError
- * if an exception occurs during static initialization of a
- * class.
- */
- public static Class<?> forName(String className) throws ClassNotFoundException {
- return forName(className, true, VMStack.getCallingClassLoader());
- }
-
- /**
- * Returns a {@code Class} object which represents the class with the
- * given name. The name should be the name of a non-primitive class, as described in
- * the {@link Class class definition}.
- * Primitive types can not be found using this method; use {@code int.class} or {@code Integer.TYPE} instead.
- *
- * <p>If the class has not yet been loaded, it is loaded first, using the given class loader.
- * If the class has not yet been initialized and {@code shouldInitialize} is true,
- * the class will be initialized.
- *
- * @throws ClassNotFoundException
- * if the requested class can not be found.
- * @throws LinkageError
- * if an error occurs during linkage
- * @throws ExceptionInInitializerError
- * if an exception occurs during static initialization of a
- * class.
- */
- public static Class<?> forName(String className, boolean shouldInitialize,
- ClassLoader classLoader) throws ClassNotFoundException {
-
- if (classLoader == null) {
- classLoader = ClassLoader.getSystemClassLoader();
- }
- // Catch an Exception thrown by the underlying native code. It wraps
- // up everything inside a ClassNotFoundException, even if e.g. an
- // Error occurred during initialization. This as a workaround for
- // an ExceptionInInitializerError that's also wrapped. It is actually
- // expected to be thrown. Maybe the same goes for other errors.
- // Not wrapping up all the errors will break android though.
- Class<?> result;
- try {
- result = classForName(className, shouldInitialize,
- classLoader);
- } catch (ClassNotFoundException e) {
- Throwable cause = e.getCause();
- if (cause instanceof ExceptionInInitializerError) {
- throw (ExceptionInInitializerError) cause;
- }
- throw e;
- }
- return result;
- }
-
- private static native Class<?> classForName(String className, boolean shouldInitialize,
- ClassLoader classLoader) throws ClassNotFoundException;
-
- /**
- * Returns an array containing {@code Class} objects for all public classes
- * and interfaces that are members of this class. This includes public
- * members inherited from super classes and interfaces. If there are no such
- * class members or if this object represents a primitive type then an array
- * of length 0 is returned.
- */
- public Class<?>[] getClasses() {
- Class<?>[] result = getDeclaredClasses(this, true);
- // Traverse all superclasses.
- for (Class<?> c = this.getSuperclass(); c != null; c = c.getSuperclass()) {
- Class<?>[] temp = getDeclaredClasses(c, true);
- if (temp.length != 0) {
- result = arraycopy(new Class[result.length + temp.length], result, temp);
- }
- }
- return result;
- }
-
- @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
-
- A annotation = getDeclaredAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
-
- if (annotationType.isAnnotationPresent(Inherited.class)) {
- for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
- annotation = sup.getDeclaredAnnotation(annotationType);
- if (annotation != null) {
- return annotation;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns an array containing all the annotations of this class. If there are no annotations
- * then an empty array is returned.
- *
- * @see #getDeclaredAnnotations()
- */
- public Annotation[] getAnnotations() {
- /*
- * 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>();
- Annotation[] declaredAnnotations = getDeclaredAnnotations();
-
- for (int i = declaredAnnotations.length-1; i >= 0; --i) {
- map.put(declaredAnnotations[i].annotationType(), declaredAnnotations[i]);
- }
- for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
- declaredAnnotations = sup.getDeclaredAnnotations();
- for (int i = declaredAnnotations.length-1; i >= 0; --i) {
- Class<?> clazz = declaredAnnotations[i].annotationType();
- if (!map.containsKey(clazz) && clazz.isAnnotationPresent(Inherited.class)) {
- map.put(clazz, declaredAnnotations[i]);
- }
- }
- }
-
- /* convert annotation values from HashMap to array */
- Collection<Annotation> coll = map.values();
- return coll.toArray(new Annotation[coll.size()]);
- }
-
- /**
- * Returns the canonical name of this class. If this class does not have a
- * canonical name as defined in the Java Language Specification, then the
- * method returns {@code null}.
- */
- public String getCanonicalName() {
- if (isLocalClass() || isAnonymousClass())
- return null;
-
- if (isArray()) {
- /*
- * The canonical name of an array type depends on the (existence of)
- * the component type's canonical name.
- */
- String name = getComponentType().getCanonicalName();
- if (name != null) {
- return name + "[]";
- }
- } else if (isMemberClass()) {
- /*
- * The canonical name of an inner class depends on the (existence
- * of) the declaring class' canonical name.
- */
- String name = getDeclaringClass().getCanonicalName();
- if (name != null) {
- return name + "." + getSimpleName();
- }
- } else {
- /*
- * The canonical name of a top-level class or primitive type is
- * equal to the fully qualified name.
- */
- return getName();
- }
-
- /*
- * Other classes don't have a canonical name.
- */
- return null;
- }
-
- /**
- * Returns the class loader which was used to load the class represented by
- * this {@code Class}. Implementations are free to return {@code null} for
- * classes that were loaded by the bootstrap class loader. The Android
- * reference implementation, though, always returns a reference to an actual
- * class loader.
- */
- public ClassLoader getClassLoader() {
- if (this.isPrimitive()) {
- return null;
- }
-
- ClassLoader loader = getClassLoaderImpl();
- if (loader == null) {
- loader = BootClassLoader.getInstance();
- }
- return loader;
- }
-
- /**
- * This must be provided by the VM vendor, as it is used by other provided
- * class implementations in this package. Outside of this class, it is used
- * by SecurityManager.classLoaderDepth(),
- * currentClassLoader() and currentLoadedClass(). Return the ClassLoader for
- * this Class without doing any security checks. The bootstrap ClassLoader
- * is returned, unlike getClassLoader() which returns null in place of the
- * bootstrap ClassLoader.
- */
- ClassLoader getClassLoaderImpl() {
- ClassLoader loader = getClassLoader(this);
- return loader == null ? BootClassLoader.getInstance() : loader;
- }
-
- /*
- * Returns the defining class loader for the given class.
- */
- private static native ClassLoader getClassLoader(Class<?> c);
-
- /**
- * Returns a {@code Class} object which represents the component type if
- * this class represents an array type. Returns {@code null} if this class
- * does not represent an array type. The component type of an array type is
- * the type of the elements of the array.
- */
- public native Class<?> getComponentType();
-
- /**
- * Returns a {@code Constructor} object which represents the public
- * 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.
- */
- @SuppressWarnings("unchecked")
- public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException {
- return (Constructor) getConstructorOrMethod("<init>", false, true, parameterTypes);
- }
-
- /**
- * Returns a constructor or method with the given name. Use "<init>" to return a constructor.
- */
- private Member getConstructorOrMethod(String name, boolean searchSuperTypes,
- boolean publicOnly, Class<?>[] parameterTypes) throws NoSuchMethodException {
- if (searchSuperTypes && !publicOnly) {
- throw new AssertionError(); // can't lookup non-public members recursively
- }
- if (name == null) {
- throw new NullPointerException("name == null");
- }
- if (parameterTypes == null) {
- parameterTypes = EmptyArray.CLASS;
- }
- for (Class<?> c : parameterTypes) {
- if (c == null) {
- throw new NoSuchMethodException("parameter type is null");
- }
- }
- Member result = searchSuperTypes
- ? getPublicConstructorOrMethodRecursive(name, parameterTypes)
- : Class.getDeclaredConstructorOrMethod(this, name, parameterTypes);
- if (result == null || publicOnly && (result.getModifiers() & Modifier.PUBLIC) == 0) {
- throw new NoSuchMethodException(name + " " + Arrays.toString(parameterTypes));
- }
- return result;
- }
-
- private Member getPublicConstructorOrMethodRecursive(String name, Class<?>[] parameterTypes) {
- // search superclasses
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- Member result = Class.getDeclaredConstructorOrMethod(c, name, parameterTypes);
- if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
- return result;
- }
- }
-
- // search implemented interfaces
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Class<?> ifc : c.getInterfaces()) {
- Member result = ifc.getPublicConstructorOrMethodRecursive(name, parameterTypes);
- if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
- return result;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns an array containing {@code Constructor} objects for all public
- * constructors for this {@code Class}. If there
- * are no public constructors or if this {@code Class} represents an array
- * class, a primitive type or void then an empty array is returned.
- *
- * @see #getDeclaredConstructors()
- */
- public Constructor<?>[] getConstructors() {
- return getDeclaredConstructors(this, true);
- }
-
- /**
- * Returns the annotations that are directly defined on the class
- * represented by this {@code Class}. Annotations that are inherited are not
- * included in the result. If there are no annotations at all, an empty
- * array is returned.
- *
- * @see #getAnnotations()
- */
- public native Annotation[] getDeclaredAnnotations();
-
- /**
- * Returns the annotation if it exists.
- */
- native private <A extends Annotation> A getDeclaredAnnotation(Class<A> annotationClass);
-
- /**
- * Returns true if the annotation exists.
- */
- native private boolean isDeclaredAnnotationPresent(Class<? extends Annotation> annotationClass);
-
- /**
- * Returns an array containing {@code Class} objects for all classes and
- * interfaces that are declared as members of the class which this {@code
- * Class} represents. If there are no classes or interfaces declared or if
- * this class represents an array class, a primitive type or void, then an
- * empty array is returned.
- */
- public Class<?>[] getDeclaredClasses() {
- return getDeclaredClasses(this, false);
- }
-
- /*
- * Returns the list of member classes of the given class.
- * If no members exist, an empty array is returned.
- */
- private static native Class<?>[] getDeclaredClasses(Class<?> c, boolean publicOnly);
-
- /**
- * Returns a {@code Constructor} object which represents the constructor
- * matching the given parameter types that is declared by the class
- * 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.
- */
- @SuppressWarnings("unchecked")
- public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
- throws NoSuchMethodException {
- return (Constructor) getConstructorOrMethod("<init>", false, false, parameterTypes);
- }
-
- /**
- * Returns an array containing {@code Constructor} objects for all
- * constructors declared in the class represented by this {@code Class}. If
- * there are no constructors or if this {@code Class} represents an array
- * class, a primitive type, or void then an empty array is returned.
- *
- * @see #getConstructors()
- */
- public Constructor<?>[] getDeclaredConstructors() {
- return getDeclaredConstructors(this, false);
- }
-
- /*
- * Returns the list of constructors. If no constructors exist, an empty array is returned.
- */
- private static native <T> Constructor<T>[] getDeclaredConstructors(Class<T> c,
- boolean publicOnly);
-
- /**
- * Returns a {@code Field} object for the field with the given name
- * which is declared in the class represented by this {@code Class}.
- *
- * @throws NoSuchFieldException if the requested field can not be found.
- * @see #getField(String)
- */
- public Field getDeclaredField(String name) throws NoSuchFieldException {
- if (name == null) {
- throw new NullPointerException("name == null");
- }
- Field result = getDeclaredField(this, name);
- if (result == null) {
- throw new NoSuchFieldException(name);
- }
- return result;
- }
-
- /**
- * Returns an array containing {@code Field} objects for all fields declared
- * in the class represented by this {@code Class}. If there are no fields or
- * if this {@code Class} represents an array class, a primitive type or void
- * then an empty array is returned.
- *
- * @see #getFields()
- */
- public Field[] getDeclaredFields() {
- return getDeclaredFields(this, false);
- }
-
- /*
- * Returns the list of fields without performing any security checks
- * first. If no fields exist at all, an empty array is returned.
- */
- static native Field[] getDeclaredFields(Class<?> c, boolean publicOnly);
-
- /**
- * Returns the field if it is defined by {@code c}; null otherwise. This
- * may return a non-public member.
- */
- static native Field getDeclaredField(Class<?> c, String name);
-
- /**
- * Returns a {@code Method} object which represents the method matching the
- * given name and parameter types that is declared by the class
- * 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}.
- */
- public Method getDeclaredMethod(String name, Class<?>... parameterTypes)
- throws NoSuchMethodException {
- Member member = getConstructorOrMethod(name, false, false, parameterTypes);
- if (member instanceof Constructor) {
- throw new NoSuchMethodException(name);
- }
- return (Method) member;
- }
-
- /**
- * Returns an array containing {@code Method} objects for all methods
- * declared in the class represented by this {@code Class}. If there are no
- * methods or if this {@code Class} represents an array class, a primitive
- * type or void then an empty array is returned.
- *
- * @see #getMethods()
- */
- public Method[] getDeclaredMethods() {
- return getDeclaredMethods(this, false);
- }
-
- /**
- * Returns the list of methods. If no methods exist, an empty array is returned.
- */
- static native Method[] getDeclaredMethods(Class<?> c, boolean publicOnly);
-
- /**
- * Returns the constructor or method if it is defined by {@code c}; null
- * otherwise. This may return a non-public member. Use "<init>" to get a constructor.
- */
- static native Member getDeclaredConstructorOrMethod(Class c, String name, Class[] args);
-
- /**
- * Returns the declaring {@code Class} of this {@code Class}. Returns
- * {@code null} if the class is not a member of another class or if this
- * {@code Class} represents an array class, a primitive type, or void.
- */
- public native Class<?> getDeclaringClass();
-
- /**
- * Returns the enclosing {@code Class} of this {@code Class}. If there is no
- * enclosing class the method returns {@code null}.
- */
- public native Class<?> getEnclosingClass();
-
- /**
- * Returns the enclosing {@code Constructor} of this {@code Class}, if it is an
- * anonymous or local/automatic class; otherwise {@code null}.
- */
- public native Constructor<?> getEnclosingConstructor();
-
- /**
- * Returns the enclosing {@code Method} of this {@code Class}, if it is an
- * anonymous or local/automatic class; otherwise {@code null}.
- */
- public native Method getEnclosingMethod();
-
- /**
- * Returns the {@code enum} constants associated with this {@code Class}.
- * Returns {@code null} if this {@code Class} does not represent an {@code
- * enum} type.
- */
- @SuppressWarnings("unchecked") // we only cast after confirming that this class is an enum
- public T[] getEnumConstants() {
- if (!isEnum()) {
- return null;
- }
- return (T[]) Enum.getSharedConstants((Class) this).clone();
- }
-
- /**
- * Returns a {@code Field} object which represents the public field with the
- * given name. This method first searches the class C represented by
- * this {@code Class}, then the interfaces implemented by C and finally the
- * superclasses of C.
- *
- * @throws NoSuchFieldException
- * if the field can not be found.
- * @see #getDeclaredField(String)
- */
- public Field getField(String name) throws NoSuchFieldException {
- if (name == null) {
- throw new NullPointerException("name == null");
- }
- Field result = getPublicFieldRecursive(name);
- if (result == null) {
- throw new NoSuchFieldException(name);
- }
- return result;
- }
-
- private Field getPublicFieldRecursive(String name) {
- // search superclasses
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- Field result = Class.getDeclaredField(c, name);
- if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
- return result;
- }
- }
-
- // search implemented interfaces
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Class<?> ifc : c.getInterfaces()) {
- Field result = ifc.getPublicFieldRecursive(name);
- if (result != null && (result.getModifiers() & Modifier.PUBLIC) != 0) {
- return result;
- }
- }
- }
-
- return null;
- }
-
- /**
- * Returns an array containing {@code Field} objects for all public fields
- * for the class C represented by this {@code Class}. Fields may be declared
- * in C, the interfaces it implements or in the superclasses of C. The
- * elements in the returned array are in no particular order.
- *
- * <p>If there are no public fields or if this class represents an array class,
- * a primitive type or {@code void} then an empty array is returned.
- *
- * @see #getDeclaredFields()
- */
- public Field[] getFields() {
- List<Field> fields = new ArrayList<Field>();
- getPublicFieldsRecursive(fields);
-
- /*
- * The result may include duplicates when this class implements an interface
- * through multiple paths. Remove those duplicates.
- */
- CollectionUtils.removeDuplicates(fields, Field.ORDER_BY_NAME_AND_DECLARING_CLASS);
- return fields.toArray(new Field[fields.size()]);
- }
-
- /**
- * Populates {@code result} with public fields defined by this class, its
- * superclasses, and all implemented interfaces.
- */
- private void getPublicFieldsRecursive(List<Field> result) {
- // search superclasses
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Field field : Class.getDeclaredFields(c, true)) {
- result.add(field);
- }
- }
-
- // search implemented interfaces
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Class<?> ifc : c.getInterfaces()) {
- ifc.getPublicFieldsRecursive(result);
- }
- }
- }
-
- /**
- * Returns the {@link Type}s of the interfaces that this {@code Class} directly
- * implements. If the {@code Class} represents a primitive type or {@code
- * void} then an empty array is returned.
- */
- public Type[] getGenericInterfaces() {
- Type[] result;
- synchronized (Caches.genericInterfaces) {
- result = Caches.genericInterfaces.get(this);
- if (result == null) {
- String annotationSignature = AnnotationAccess.getSignature(this);
- if (annotationSignature == null) {
- result = getInterfaces();
- } else {
- GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, annotationSignature);
- result = Types.getTypeArray(parser.interfaceTypes, false);
- }
- Caches.genericInterfaces.put(this, result);
- }
- }
- return (result.length == 0) ? result : result.clone();
- }
-
- /**
- * Returns the {@code Type} that represents the superclass of this {@code
- * class}.
- */
- public Type getGenericSuperclass() {
- Type genericSuperclass = getSuperclass();
- // This method is specified to return null for all cases where getSuperclass
- // returns null, i.e, for primitives, interfaces, void and java.lang.Object.
-
- if (genericSuperclass == null) {
- return null;
- }
- String annotationSignature = AnnotationAccess.getSignature(this);
- if (annotationSignature != null) {
- GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, annotationSignature);
- genericSuperclass = parser.superclassType;
- }
- return Types.getType(genericSuperclass);
- }
-
- /**
- * Returns an array of {@code Class} objects that match the interfaces
- * in the {@code implements} declaration of the class represented
- * by this {@code Class}. The order of the elements in the array is
- * identical to the order in the original class declaration. If the class
- * does not implement any interfaces, an empty array is returned.
- */
- public native Class<?>[] getInterfaces();
-
- /**
- * 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.
- *
- * <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.
- */
- public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException {
- Member member = getConstructorOrMethod(name, true, true, parameterTypes);
- if (member instanceof Constructor) {
- throw new NoSuchMethodException(name);
- }
- return (Method) member;
- }
-
- /**
- * Returns an array containing {@code Method} objects for all public methods
- * for the class C represented by this {@code Class}. Methods may be
- * declared in C, the interfaces it implements or in the superclasses of C.
- * The elements in the returned array are in no particular order.
- *
- * <p>If there are no public methods or if this {@code Class} represents a
- * primitive type or {@code void} then an empty array is returned.
- *
- * @see #getDeclaredMethods()
- */
- public Method[] getMethods() {
- List<Method> methods = new ArrayList<Method>();
- getPublicMethodsRecursive(methods);
-
- /*
- * Remove methods defined by multiple types, preferring to keep methods
- * declared by derived types.
- */
- CollectionUtils.removeDuplicates(methods, Method.ORDER_BY_SIGNATURE);
- return methods.toArray(new Method[methods.size()]);
- }
-
- /**
- * Populates {@code result} with public methods defined by this class, its
- * superclasses, and all implemented interfaces, including overridden methods.
- */
- private void getPublicMethodsRecursive(List<Method> result) {
- // search superclasses
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Method method : Class.getDeclaredMethods(c, true)) {
- result.add(method);
- }
- }
-
- // search implemented interfaces
- for (Class<?> c = this; c != null; c = c.getSuperclass()) {
- for (Class<?> ifc : c.getInterfaces()) {
- ifc.getPublicMethodsRecursive(result);
- }
- }
- }
-
- /**
- * Returns an integer that represents the modifiers of the class represented
- * by this {@code Class}. The returned value is a combination of bits
- * defined by constants in the {@link Modifier} class.
- */
- public int getModifiers() {
- return getModifiers(this, false);
- }
-
- /*
- * Returns the modifiers for the given class.
- *
- * {@code ignoreInnerClassesAttrib} determines whether we look for and use the
- * flags from an "inner class" attribute
- */
- private static native int getModifiers(Class<?> clazz, boolean ignoreInnerClassesAttrib);
-
- /**
- * Returns the name of the class represented by this {@code Class}. For a
- * description of the format which is used, see the class definition of
- * {@link Class}.
- */
- public String getName() {
- String result = name;
- return (result == null) ? (name = getNameNative()) : result;
- }
-
- private native String getNameNative();
-
- /**
- * Returns the simple name of the class represented by this {@code Class} as
- * defined in the source code. If there is no name (that is, the class is
- * anonymous) then an empty string is returned. If the receiver is an array
- * then the name of the underlying type with square braces appended (for
- * example {@code "Integer[]"}) is returned.
- *
- * @return the simple name of the class represented by this {@code Class}.
- */
- public String getSimpleName() {
- if (isArray()) {
- return getComponentType().getSimpleName() + "[]";
- }
-
- String name = getName();
-
- if (isAnonymousClass()) {
- return "";
- }
-
- if (isMemberClass() || isLocalClass()) {
- return getInnerClassName();
- }
-
- int dot = name.lastIndexOf('.');
- if (dot != -1) {
- return name.substring(dot + 1);
- }
-
- return name;
- }
-
- /*
- * Returns the simple name of a member or local class, or null otherwise.
- */
- private native String getInnerClassName();
-
- /**
- * Returns null.
- */
- public ProtectionDomain getProtectionDomain() {
- return null;
- }
-
- /**
- * Returns the URL of the given resource, or null if the resource is not found.
- * The mapping between the resource name and the URL is managed by the class' class loader.
- *
- * @see ClassLoader
- */
- public URL getResource(String resourceName) {
- // Get absolute resource name, but without the leading slash
- if (resourceName.startsWith("/")) {
- resourceName = resourceName.substring(1);
- } else {
- String pkg = getName();
- int dot = pkg.lastIndexOf('.');
- if (dot != -1) {
- pkg = pkg.substring(0, dot).replace('.', '/');
- } else {
- pkg = "";
- }
-
- resourceName = pkg + "/" + resourceName;
- }
-
- // Delegate to proper class loader
- ClassLoader loader = getClassLoader();
- if (loader != null) {
- return loader.getResource(resourceName);
- } else {
- return ClassLoader.getSystemResource(resourceName);
- }
- }
-
- /**
- * Returns a read-only stream for the contents of the given resource, or null if the resource
- * is not found.
- * The mapping between the resource name and the stream is managed by the class' class loader.
- *
- * @see ClassLoader
- */
- public InputStream getResourceAsStream(String resourceName) {
- // Get absolute resource name, but without the leading slash
- if (resourceName.startsWith("/")) {
- resourceName = resourceName.substring(1);
- } else {
- String pkg = getName();
- int dot = pkg.lastIndexOf('.');
- if (dot != -1) {
- pkg = pkg.substring(0, dot).replace('.', '/');
- } else {
- pkg = "";
- }
-
- resourceName = pkg + "/" + resourceName;
- }
-
- // Delegate to proper class loader
- ClassLoader loader = getClassLoader();
- if (loader != null) {
- return loader.getResourceAsStream(resourceName);
- } else {
- return ClassLoader.getSystemResourceAsStream(resourceName);
- }
- }
-
- /**
- * Returns null. (On Android, a {@code ClassLoader} can load classes from multiple dex files.
- * All classes from any given dex file will have the same signers, but different dex
- * files may have different signers. This does not fit well with the original
- * {@code ClassLoader}-based model of {@code getSigners}.)
- */
- public Object[] getSigners() {
- // See http://code.google.com/p/android/issues/detail?id=1766.
- return null;
- }
-
- /**
- * Returns the {@code Class} object which represents the superclass of the
- * class represented by this {@code Class}. If this {@code Class} represents
- * the {@code Object} class, a primitive type, an interface or void then the
- * method returns {@code null}. If this {@code Class} represents an array
- * class then the {@code Object} class is returned.
- */
- public native Class<? super T> getSuperclass();
-
- /**
- * Returns an array containing {@code TypeVariable} objects for type
- * variables declared by the generic class represented by this {@code
- * Class}. Returns an empty array if the class is not generic.
- */
- @SuppressWarnings("unchecked")
- public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
- String annotationSignature = AnnotationAccess.getSignature(this);
- if (annotationSignature == null) {
- return EmptyArray.TYPE_VARIABLE;
- }
- GenericSignatureParser parser = new GenericSignatureParser(getClassLoader());
- parser.parseForClass(this, annotationSignature);
- return parser.formalTypeParameters;
- }
-
- /**
- * Tests whether this {@code Class} represents an annotation class.
- */
- public boolean isAnnotation() {
- final int ACC_ANNOTATION = 0x2000; // not public in reflect.Modifiers
- int mod = getModifiers(this, true);
- return (mod & ACC_ANNOTATION) != 0;
- }
-
- @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
-
- if (isDeclaredAnnotationPresent(annotationType)) {
- return true;
- }
-
- if (annotationType.isDeclaredAnnotationPresent(Inherited.class)) {
- for (Class<?> sup = getSuperclass(); sup != null; sup = sup.getSuperclass()) {
- if (sup.isDeclaredAnnotationPresent(annotationType)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Tests whether the class represented by this {@code Class} is
- * anonymous.
- */
- native public boolean isAnonymousClass();
-
- /**
- * Tests whether the class represented by this {@code Class} is an array class.
- */
- public boolean isArray() {
- return getComponentType() != null;
- }
-
- /**
- * Tests whether the given class type can be converted to the class
- * represented by this {@code Class}. Conversion may be done via an identity
- * conversion or a widening reference conversion (if either the receiver or
- * the argument represent primitive types, only the identity conversion
- * applies).
- *
- * @throws NullPointerException
- * if {@code c} is {@code null}.
- */
- public native boolean isAssignableFrom(Class<?> c);
-
- /**
- * Tests whether the class represented by this {@code Class} is an
- * {@code enum}.
- */
- public boolean isEnum() {
- if (getSuperclass() != Enum.class) {
- return false;
- }
- int mod = getModifiers(this, true);
- return (mod & 0x4000) != 0;
- }
-
- /**
- * Tests whether the given object can be cast to the class
- * represented by this {@code Class}. This is the runtime version of the
- * {@code instanceof} operator.
- *
- * @return {@code true} if {@code object} can be cast to the type
- * represented by this {@code Class}; {@code false} if {@code
- * object} is {@code null} or cannot be cast.
- */
- public native boolean isInstance(Object object);
-
- /**
- * Tests whether this {@code Class} represents an interface.
- */
- public native boolean isInterface();
-
- /**
- * Tests whether the class represented by this {@code Class} is defined
- * locally.
- */
- public boolean isLocalClass() {
- boolean enclosed = (getEnclosingMethod() != null ||
- getEnclosingConstructor() != null);
- return enclosed && !isAnonymousClass();
- }
-
- /**
- * Tests whether the class represented by this {@code Class} is a member
- * class.
- */
- public boolean isMemberClass() {
- return getDeclaringClass() != null;
- }
-
- /**
- * Tests whether this {@code Class} represents a primitive type.
- */
- public native boolean isPrimitive();
-
- /**
- * Tests whether this {@code Class} represents a synthetic type.
- */
- public boolean isSynthetic() {
- final int ACC_SYNTHETIC = 0x1000; // not public in reflect.Modifiers
- int mod = getModifiers(this, true);
- return (mod & ACC_SYNTHETIC) != 0;
- }
-
- /**
- * Returns a new instance of the class represented by this {@code Class},
- * created by invoking the default (that is, zero-argument) constructor. If
- * there is no such constructor, or if the creation fails (either because of
- * a lack of available memory or because an exception is thrown by the
- * constructor), an {@code InstantiationException} is thrown. If the default
- * constructor exists but is not accessible from the context where this
- * method is invoked, an {@code IllegalAccessException} is thrown.
- *
- * @throws IllegalAccessException
- * if the default constructor is not visible.
- * @throws InstantiationException
- * if the instance can not be created.
- */
- public T newInstance() throws InstantiationException, IllegalAccessException {
- return newInstanceImpl();
- }
-
- private native T newInstanceImpl() throws IllegalAccessException, InstantiationException;
-
- @Override
- public String toString() {
- if (isPrimitive()) {
- return getSimpleName();
- }
- return (isInterface() ? "interface " : "class ") + getName();
- }
-
- /**
- * Returns the {@code Package} of which the class represented by this
- * {@code Class} is a member. Returns {@code null} if no {@code Package}
- * object was created by the class loader of the class.
- */
- public Package getPackage() {
- // TODO This might be a hack, but the VM doesn't have the necessary info.
- ClassLoader loader = getClassLoader();
- if (loader != null) {
- String name = getName();
- int dot = name.lastIndexOf('.');
- return (dot != -1 ? loader.getPackage(name.substring(0, dot)) : null);
- }
- return null;
- }
-
- /**
- * Returns the assertion status for the class represented by this {@code
- * Class}. Assertion is enabled / disabled based on the class loader,
- * package or class default at runtime.
- */
- public native boolean desiredAssertionStatus();
-
- /**
- * Casts this {@code Class} to represent a subclass of the given class.
- * If successful, this {@code Class} is returned; otherwise a {@code
- * ClassCastException} is thrown.
- *
- * @throws ClassCastException
- * if this {@code Class} cannot be cast to the given type.
- */
- @SuppressWarnings("unchecked")
- public <U> Class<? extends U> asSubclass(Class<U> c) {
- if (c.isAssignableFrom(this)) {
- return (Class<? extends U>)this;
- }
- String actualClassName = this.getName();
- String desiredClassName = c.getName();
- throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
- }
-
- /**
- * Casts the given object to the type represented by this {@code Class}.
- * If the object is {@code null} then the result is also {@code null}.
- *
- * @throws ClassCastException
- * if the object cannot be cast to the given type.
- */
- @SuppressWarnings("unchecked")
- public T cast(Object obj) {
- if (obj == null) {
- return null;
- } else if (this.isInstance(obj)) {
- return (T)obj;
- }
- String actualClassName = obj.getClass().getName();
- String desiredClassName = this.getName();
- throw new ClassCastException(actualClassName + " cannot be cast to " + desiredClassName);
- }
-
- /**
- * Copies two arrays into one. Assumes that the destination array is large
- * enough.
- *
- * @param result the destination array
- * @param head the first source array
- * @param tail the second source array
- * @return the destination array, that is, result
- */
- private static <T extends Object> T[] arraycopy(T[] result, T[] head, T[] tail) {
- System.arraycopy(head, 0, result, 0, head.length);
- 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 getDexAnnotationDirectoryOffset() {
- Dex dex = getDex();
- if (dex == null) {
- return 0;
- }
- int classDefIndex = getDexClassDefIndex();
- if (classDefIndex < 0) {
- return 0;
- }
- return dex.annotationDirectoryOffsetFromClassDefIndex(classDefIndex);
- }
-
-
- /**
- * Returns a resolved type from the dex cache, computing the type from the dex file if
- * necessary.
- * TODO: use Dalvik's dex cache.
- * @hide
- */
- public Class<?> getDexCacheType(Dex dex, int typeIndex) {
- String internalName = dex.typeNames().get(typeIndex);
- return InternalNames.getClass(getClassLoader(), internalName);
- }
-
- /**
- * Returns a string from the dex cache, computing the string from the dex file if necessary.
- *
- * @hide
- */
- public String getDexCacheString(Dex dex, int dexStringIndex) {
- return dex.strings().get(dexStringIndex);
- }
-
-
- private static class Caches {
- /**
- * Cache to avoid frequent recalculation of generic interfaces, which is generally uncommon.
- * Sized sufficient to allow ConcurrentHashMapTest to run without recalculating its generic
- * interfaces (required to avoid time outs). Validated by running reflection heavy code
- * such as applications using Guice-like frameworks.
- */
- private static final BasicLruCache<Class, Type[]> genericInterfaces
- = new BasicLruCache<Class, Type[]>(8);
- }
-}
diff --git a/libdvm/src/main/java/java/lang/ClassLoader.java b/libdvm/src/main/java/java/lang/ClassLoader.java
deleted file mode 100644
index c6a80913..0000000
--- a/libdvm/src/main/java/java/lang/ClassLoader.java
+++ /dev/null
@@ -1,836 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import dalvik.system.PathClassLoader;
-import dalvik.system.VMStack;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.nio.ByteBuffer;
-import java.security.ProtectionDomain;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Loads classes and resources from a repository. One or more class loaders are
- * installed at runtime. These are consulted whenever the runtime system needs a
- * specific class that is not yet available in-memory. Typically, class loaders
- * are grouped into a tree where child class loaders delegate all requests to
- * parent class loaders. Only if the parent class loader cannot satisfy the
- * request, the child class loader itself tries to handle it.
- * <p>
- * {@code ClassLoader} is an abstract class that implements the common
- * infrastructure required by all class loaders. Android provides several
- * concrete implementations of the class, with
- * {@link dalvik.system.PathClassLoader} being the one typically used. Other
- * applications may implement subclasses of {@code ClassLoader} to provide
- * special ways for loading classes.
- * </p>
- * @see Class
- */
-public abstract class ClassLoader {
-
- /**
- * The 'System' ClassLoader - the one that is responsible for loading
- * classes from the classpath. It is not equal to the bootstrap class loader -
- * that one handles the built-in classes.
- *
- * Because of a potential class initialization race between ClassLoader and
- * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
- * creation of the system class loader until first use. We use a static
- * inner class to get synchronization at init time without having to sync on
- * every access.
- *
- * @see #getSystemClassLoader()
- */
- static private class SystemClassLoader {
- public static ClassLoader loader = ClassLoader.createSystemClassLoader();
- }
-
- /**
- * The parent ClassLoader.
- */
- private ClassLoader parent;
-
- /**
- * The packages known to the class loader.
- */
- private Map<String, Package> packages = new HashMap<String, Package>();
-
- /**
- * Create the system class loader. Note this is NOT the bootstrap class
- * loader (which is managed by the VM). We use a null value for the parent
- * to indicate that the bootstrap loader is our parent.
- */
- private static ClassLoader createSystemClassLoader() {
- String classPath = System.getProperty("java.class.path", ".");
-
- // String[] paths = classPath.split(":");
- // URL[] urls = new URL[paths.length];
- // for (int i = 0; i < paths.length; i++) {
- // try {
- // urls[i] = new URL("file://" + paths[i]);
- // }
- // catch (Exception ex) {
- // ex.printStackTrace();
- // }
- // }
- //
- // return new java.net.URLClassLoader(urls, null);
-
- // TODO Make this a java.net.URLClassLoader once we have those?
- return new PathClassLoader(classPath, BootClassLoader.getInstance());
- }
-
- /**
- * Returns the system class loader. This is the parent for new
- * {@code ClassLoader} instances and is typically the class loader used to
- * start the application.
- */
- public static ClassLoader getSystemClassLoader() {
- return SystemClassLoader.loader;
- }
-
- /**
- * Finds the URL of the resource with the specified name. The system class
- * loader's resource lookup algorithm is used to find the resource.
- *
- * @return the {@code URL} object for the requested resource or {@code null}
- * if the resource can not be found.
- * @param resName
- * the name of the resource to find.
- * @see Class#getResource
- */
- public static URL getSystemResource(String resName) {
- return SystemClassLoader.loader.getResource(resName);
- }
-
- /**
- * Returns an enumeration of URLs for the resource with the specified name.
- * The system class loader's resource lookup algorithm is used to find the
- * resource.
- *
- * @return an enumeration of {@code URL} objects containing the requested
- * resources.
- * @param resName
- * the name of the resource to find.
- * @throws IOException
- * if an I/O error occurs.
- */
- public static Enumeration<URL> getSystemResources(String resName) throws IOException {
- return SystemClassLoader.loader.getResources(resName);
- }
-
- /**
- * Returns a stream for the resource with the specified name. The system
- * class loader's resource lookup algorithm is used to find the resource.
- * Basically, the contents of the java.class.path are searched in order,
- * looking for a path which matches the specified resource.
- *
- * @return a stream for the resource or {@code null}.
- * @param resName
- * the name of the resource to find.
- * @see Class#getResourceAsStream
- */
- public static InputStream getSystemResourceAsStream(String resName) {
- return SystemClassLoader.loader.getResourceAsStream(resName);
- }
-
- /**
- * Constructs a new instance of this class with the system class loader as
- * its parent.
- */
- protected ClassLoader() {
- this(getSystemClassLoader(), false);
- }
-
- /**
- * Constructs a new instance of this class with the specified class loader
- * as its parent.
- *
- * @param parentLoader
- * The {@code ClassLoader} to use as the new class loader's
- * parent.
- */
- protected ClassLoader(ClassLoader parentLoader) {
- this(parentLoader, false);
- }
-
- /*
- * constructor for the BootClassLoader which needs parent to be null.
- */
- ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
- if (parentLoader == null && !nullAllowed) {
- throw new NullPointerException("parentLoader == null && !nullAllowed");
- }
- parent = parentLoader;
- }
-
- /**
- * Constructs a new class from an array of bytes containing a class
- * definition in class file format.
- *
- * @param classRep
- * the memory image of a class file.
- * @param offset
- * the offset into {@code classRep}.
- * @param length
- * the length of the class file.
- * @return the {@code Class} object created from the specified subset of
- * data in {@code classRep}.
- * @throws ClassFormatError
- * if {@code classRep} does not contain a valid class.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0}, {@code length < 0} or if
- * {@code offset + length} is greater than the length of
- * {@code classRep}.
- * @deprecated Use {@link #defineClass(String, byte[], int, int)} instead.
- */
- @Deprecated
- protected final Class<?> defineClass(byte[] classRep, int offset, int length)
- throws ClassFormatError {
- throw new UnsupportedOperationException("can't load this type of class file");
- }
-
- /**
- * Constructs a new class from an array of bytes containing a class
- * definition in class file format.
- *
- * @param className
- * the expected name of the new class, may be {@code null} if not
- * known.
- * @param classRep
- * the memory image of a class file.
- * @param offset
- * the offset into {@code classRep}.
- * @param length
- * the length of the class file.
- * @return the {@code Class} object created from the specified subset of
- * data in {@code classRep}.
- * @throws ClassFormatError
- * if {@code classRep} does not contain a valid class.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0}, {@code length < 0} or if
- * {@code offset + length} is greater than the length of
- * {@code classRep}.
- */
- protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
- throws ClassFormatError {
- throw new UnsupportedOperationException("can't load this type of class file");
- }
-
- /**
- * Constructs a new class from an array of bytes containing a class
- * definition in class file format and assigns the specified protection
- * domain to the new class. If the provided protection domain is
- * {@code null} then a default protection domain is assigned to the class.
- *
- * @param className
- * the expected name of the new class, may be {@code null} if not
- * known.
- * @param classRep
- * the memory image of a class file.
- * @param offset
- * the offset into {@code classRep}.
- * @param length
- * the length of the class file.
- * @param protectionDomain
- * the protection domain to assign to the loaded class, may be
- * {@code null}.
- * @return the {@code Class} object created from the specified subset of
- * data in {@code classRep}.
- * @throws ClassFormatError
- * if {@code classRep} does not contain a valid class.
- * @throws IndexOutOfBoundsException
- * if {@code offset < 0}, {@code length < 0} or if
- * {@code offset + length} is greater than the length of
- * {@code classRep}.
- * @throws NoClassDefFoundError
- * if {@code className} is not equal to the name of the class
- * contained in {@code classRep}.
- */
- protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
- ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
- throw new UnsupportedOperationException("can't load this type of class file");
- }
-
- /**
- * Defines a new class with the specified name, byte code from the byte
- * buffer and the optional protection domain. If the provided protection
- * domain is {@code null} then a default protection domain is assigned to
- * the class.
- *
- * @param name
- * the expected name of the new class, may be {@code null} if not
- * known.
- * @param b
- * the byte buffer containing the byte code of the new class.
- * @param protectionDomain
- * the protection domain to assign to the loaded class, may be
- * {@code null}.
- * @return the {@code Class} object created from the data in {@code b}.
- * @throws ClassFormatError
- * if {@code b} does not contain a valid class.
- * @throws NoClassDefFoundError
- * if {@code className} is not equal to the name of the class
- * contained in {@code b}.
- */
- protected final Class<?> defineClass(String name, ByteBuffer b,
- ProtectionDomain protectionDomain) throws ClassFormatError {
-
- byte[] temp = new byte[b.remaining()];
- b.get(temp);
- return defineClass(name, temp, 0, temp.length, protectionDomain);
- }
-
- /**
- * Overridden by subclasses, throws a {@code ClassNotFoundException} by
- * default. This method is called by {@code loadClass} after the parent
- * {@code ClassLoader} has failed to find a loaded class of the same name.
- *
- * @param className
- * the name of the class to look for.
- * @return the {@code Class} object that is found.
- * @throws ClassNotFoundException
- * if the class cannot be found.
- */
- protected Class<?> findClass(String className) throws ClassNotFoundException {
- throw new ClassNotFoundException(className);
- }
-
- /**
- * Returns the class with the specified name if it has already been loaded
- * by the VM or {@code null} if it has not yet been loaded.
- *
- * @param className
- * the name of the class to look for.
- * @return the {@code Class} object or {@code null} if the requested class
- * has not been loaded.
- */
- protected final Class<?> findLoadedClass(String className) {
- ClassLoader loader;
- if (this == BootClassLoader.getInstance())
- loader = null;
- else
- loader = this;
- return VMClassLoader.findLoadedClass(loader, className);
- }
-
- /**
- * Finds the class with the specified name, loading it using the system
- * class loader if necessary.
- *
- * @param className
- * the name of the class to look for.
- * @return the {@code Class} object with the requested {@code className}.
- * @throws ClassNotFoundException
- * if the class can not be found.
- */
- protected final Class<?> findSystemClass(String className) throws ClassNotFoundException {
- return Class.forName(className, false, getSystemClassLoader());
- }
-
- /**
- * Returns this class loader's parent.
- *
- * @return this class loader's parent or {@code null}.
- */
- public final ClassLoader getParent() {
- return parent;
- }
-
- /**
- * Returns the URL of the resource with the specified name. This
- * implementation first tries to use the parent class loader to find the
- * resource; if this fails then {@link #findResource(String)} is called to
- * find the requested resource.
- *
- * @param resName
- * the name of the resource to find.
- * @return the {@code URL} object for the requested resource or {@code null}
- * if the resource can not be found
- * @see Class#getResource
- */
- public URL getResource(String resName) {
- URL resource = parent.getResource(resName);
- if (resource == null) {
- resource = findResource(resName);
- }
- return resource;
- }
-
- /**
- * Returns an enumeration of URLs for the resource with the specified name.
- * This implementation first uses this class loader's parent to find the
- * resource, then it calls {@link #findResources(String)} to get additional
- * URLs. The returned enumeration contains the {@code URL} objects of both
- * find operations.
- *
- * @return an enumeration of {@code URL} objects for the requested resource.
- * @param resName
- * the name of the resource to find.
- * @throws IOException
- * if an I/O error occurs.
- */
- @SuppressWarnings("unchecked")
- public Enumeration<URL> getResources(String resName) throws IOException {
-
- Enumeration first = parent.getResources(resName);
- Enumeration second = findResources(resName);
-
- return new TwoEnumerationsInOne(first, second);
- }
-
- /**
- * Returns a stream for the resource with the specified name. See
- * {@link #getResource(String)} for a description of the lookup algorithm
- * used to find the resource.
- *
- * @return a stream for the resource or {@code null} if the resource can not be found
- * @param resName
- * the name of the resource to find.
- * @see Class#getResourceAsStream
- */
- public InputStream getResourceAsStream(String resName) {
- try {
- URL url = getResource(resName);
- if (url != null) {
- return url.openStream();
- }
- } catch (IOException ex) {
- // Don't want to see the exception.
- }
-
- return null;
- }
-
- /**
- * Loads the class with the specified name. Invoking this method is
- * equivalent to calling {@code loadClass(className, false)}.
- * <p>
- * <strong>Note:</strong> In the Android reference implementation, the
- * second parameter of {@link #loadClass(String, boolean)} is ignored
- * anyway.
- * </p>
- *
- * @return the {@code Class} object.
- * @param className
- * the name of the class to look for.
- * @throws ClassNotFoundException
- * if the class can not be found.
- */
- public Class<?> loadClass(String className) throws ClassNotFoundException {
- return loadClass(className, false);
- }
-
- /**
- * Loads the class with the specified name, optionally linking it after
- * loading. The following steps are performed:
- * <ol>
- * <li> Call {@link #findLoadedClass(String)} to determine if the requested
- * class has already been loaded.</li>
- * <li>If the class has not yet been loaded: Invoke this method on the
- * parent class loader.</li>
- * <li>If the class has still not been loaded: Call
- * {@link #findClass(String)} to find the class.</li>
- * </ol>
- * <p>
- * <strong>Note:</strong> In the Android reference implementation, the
- * {@code resolve} parameter is ignored; classes are never linked.
- * </p>
- *
- * @return the {@code Class} object.
- * @param className
- * the name of the class to look for.
- * @param resolve
- * Indicates if the class should be resolved after loading. This
- * parameter is ignored on the Android reference implementation;
- * classes are not resolved.
- * @throws ClassNotFoundException
- * if the class can not be found.
- */
- protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
- Class<?> clazz = findLoadedClass(className);
-
- if (clazz == null) {
- try {
- clazz = parent.loadClass(className, false);
- } catch (ClassNotFoundException e) {
- // Don't want to see this.
- }
-
- if (clazz == null) {
- clazz = findClass(className);
- }
- }
-
- return clazz;
- }
-
- /**
- * Forces a class to be linked (initialized). If the class has already been
- * linked this operation has no effect.
- * <p>
- * <strong>Note:</strong> In the Android reference implementation, this
- * method has no effect.
- * </p>
- *
- * @param clazz
- * the class to link.
- */
- protected final void resolveClass(Class<?> clazz) {
- // no-op, doesn't make sense on android.
- }
-
- /**
- * Finds the URL of the resource with the specified name. This
- * implementation just returns {@code null}; it should be overridden in
- * subclasses.
- *
- * @param resName
- * the name of the resource to find.
- * @return the {@code URL} object for the requested resource.
- */
- protected URL findResource(String resName) {
- return null;
- }
-
- /**
- * Finds an enumeration of URLs for the resource with the specified name.
- * This implementation just returns an empty {@code Enumeration}; it should
- * be overridden in subclasses.
- *
- * @param resName
- * the name of the resource to find.
- * @return an enumeration of {@code URL} objects for the requested resource.
- * @throws IOException
- * if an I/O error occurs.
- */
- @SuppressWarnings( {
- "unchecked", "unused"
- })
- protected Enumeration<URL> findResources(String resName) throws IOException {
- return Collections.emptyEnumeration();
- }
-
- /**
- * Returns the absolute path of the native library with the specified name,
- * or {@code null}. If this method returns {@code null} then the virtual
- * machine searches the directories specified by the system property
- * "java.library.path".
- * <p>
- * This implementation always returns {@code null}.
- * </p>
- *
- * @param libName
- * the name of the library to find.
- * @return the absolute path of the library.
- */
- protected String findLibrary(String libName) {
- return null;
- }
-
- /**
- * Returns the package with the specified name. Package information is
- * searched in this class loader.
- *
- * @param name
- * the name of the package to find.
- * @return the package with the requested name; {@code null} if the package
- * can not be found.
- */
- protected Package getPackage(String name) {
- synchronized (packages) {
- return packages.get(name);
- }
- }
-
- /**
- * Returns all the packages known to this class loader.
- *
- * @return an array with all packages known to this class loader.
- */
- protected Package[] getPackages() {
- synchronized (packages) {
- Collection<Package> col = packages.values();
- Package[] result = new Package[col.size()];
- col.toArray(result);
- return result;
- }
- }
-
- /**
- * Defines and returns a new {@code Package} using the specified
- * information. If {@code sealBase} is {@code null}, the package is left
- * unsealed. Otherwise, the package is sealed using this URL.
- *
- * @param name
- * the name of the package.
- * @param specTitle
- * the title of the specification.
- * @param specVersion
- * the version of the specification.
- * @param specVendor
- * the vendor of the specification.
- * @param implTitle
- * the implementation title.
- * @param implVersion
- * the implementation version.
- * @param implVendor
- * the specification vendor.
- * @param sealBase
- * the URL used to seal this package or {@code null} to leave the
- * package unsealed.
- * @return the {@code Package} object that has been created.
- * @throws IllegalArgumentException
- * if a package with the specified name already exists.
- */
- protected Package definePackage(String name, String specTitle, String specVersion,
- String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
- throws IllegalArgumentException {
-
- synchronized (packages) {
- if (packages.containsKey(name)) {
- throw new IllegalArgumentException("Package " + name + " already defined");
- }
-
- Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle,
- implVersion, implVendor, sealBase);
-
- packages.put(name, newPackage);
-
- return newPackage;
- }
- }
-
- /**
- * Sets the signers of the specified class. This implementation does
- * nothing.
- *
- * @param c
- * the {@code Class} object for which to set the signers.
- * @param signers
- * the signers for {@code c}.
- */
- protected final void setSigners(Class<?> c, Object[] signers) {
- }
-
- /**
- * Sets the assertion status of the class with the specified name.
- * <p>
- * <strong>Note: </strong>This method does nothing in the Android reference
- * implementation.
- * </p>
- *
- * @param cname
- * the name of the class for which to set the assertion status.
- * @param enable
- * the new assertion status.
- */
- public void setClassAssertionStatus(String cname, boolean enable) {
- }
-
- /**
- * Sets the assertion status of the package with the specified name.
- * <p>
- * <strong>Note: </strong>This method does nothing in the Android reference
- * implementation.
- * </p>
- *
- * @param pname
- * the name of the package for which to set the assertion status.
- * @param enable
- * the new assertion status.
- */
- public void setPackageAssertionStatus(String pname, boolean enable) {
- }
-
- /**
- * Sets the default assertion status for this class loader.
- * <p>
- * <strong>Note: </strong>This method does nothing in the Android reference
- * implementation.
- * </p>
- *
- * @param enable
- * the new assertion status.
- */
- public void setDefaultAssertionStatus(boolean enable) {
- }
-
- /**
- * Sets the default assertion status for this class loader to {@code false}
- * and removes any package default and class assertion status settings.
- * <p>
- * <strong>Note:</strong> This method does nothing in the Android reference
- * implementation.
- * </p>
- */
- public void clearAssertionStatus() {
- }
-}
-
-/*
- * Provides a helper class that combines two existing URL enumerations into one.
- * It is required for the getResources() methods. Items are fetched from the
- * first enumeration until it's empty, then from the second one.
- */
-class TwoEnumerationsInOne implements Enumeration<URL> {
-
- private Enumeration<URL> first;
-
- private Enumeration<URL> second;
-
- public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) {
- this.first = first;
- this.second = second;
- }
-
- public boolean hasMoreElements() {
- return first.hasMoreElements() || second.hasMoreElements();
- }
-
- public URL nextElement() {
- if (first.hasMoreElements()) {
- return first.nextElement();
- } else {
- return second.nextElement();
- }
- }
-
-}
-
-/**
- * Provides an explicit representation of the boot class loader. It sits at the
- * head of the class loader chain and delegates requests to the VM's internal
- * class loading mechanism.
- */
-class BootClassLoader extends ClassLoader {
-
- private static BootClassLoader instance;
-
- @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
- public static synchronized BootClassLoader getInstance() {
- if (instance == null) {
- instance = new BootClassLoader();
- }
-
- return instance;
- }
-
- public BootClassLoader() {
- super(null, true);
- }
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- return VMClassLoader.loadClass(name, false);
- }
-
- @Override
- protected URL findResource(String name) {
- return VMClassLoader.getResource(name);
- }
-
- @SuppressWarnings("unused")
- @Override
- protected Enumeration<URL> findResources(String resName) throws IOException {
- return Collections.enumeration(VMClassLoader.getResources(resName));
- }
-
- /**
- * Returns package information for the given package. Unfortunately, the
- * Android BootClassLoader doesn't really have this information, and as a
- * non-secure ClassLoader, it isn't even required to, according to the spec.
- * Yet, we want to provide it, in order to make all those hopeful callers of
- * {@code myClass.getPackage().getName()} happy. Thus we construct a Package
- * object the first time it is being requested and fill most of the fields
- * with dummy values. The Package object is then put into the ClassLoader's
- * Package cache, so we see the same one next time. We don't create Package
- * objects for null arguments or for the default package.
- * <p>
- * There a limited chance that we end up with multiple Package objects
- * representing the same package: It can happen when when a package is
- * scattered across different JAR files being loaded by different
- * ClassLoaders. Rather unlikely, and given that this whole thing is more or
- * less a workaround, probably not worth the effort.
- */
- @Override
- protected Package getPackage(String name) {
- if (name != null && !name.isEmpty()) {
- synchronized (this) {
- Package pack = super.getPackage(name);
-
- if (pack == null) {
- pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
- "Unknown", null);
- }
-
- return pack;
- }
- }
-
- return null;
- }
-
- @Override
- public URL getResource(String resName) {
- return findResource(resName);
- }
-
- @Override
- protected Class<?> loadClass(String className, boolean resolve)
- throws ClassNotFoundException {
- Class<?> clazz = findLoadedClass(className);
-
- if (clazz == null) {
- clazz = findClass(className);
- }
-
- return clazz;
- }
-
- @Override
- public Enumeration<URL> getResources(String resName) throws IOException {
- return findResources(resName);
- }
-}
-
-/**
- * TODO Open issues - Missing / empty methods - Signer stuff - Protection
- * domains - Assertions
- */
diff --git a/libdvm/src/main/java/java/lang/Daemons.java b/libdvm/src/main/java/java/lang/Daemons.java
deleted file mode 100644
index 78a4152..0000000
--- a/libdvm/src/main/java/java/lang/Daemons.java
+++ /dev/null
@@ -1,281 +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.lang;
-
-import dalvik.system.VMRuntime;
-import java.lang.ref.FinalizerReference;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.util.concurrent.TimeoutException;
-import libcore.util.EmptyArray;
-
-/**
- * Calls Object.finalize() on objects in the finalizer reference queue. The VM
- * will abort if any finalize() call takes more than the maximum finalize time
- * to complete.
- *
- * @hide
- */
-public final class Daemons {
- private static final int NANOS_PER_MILLI = 1000 * 1000;
- private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000;
- private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND;
-
- public static void start() {
- ReferenceQueueDaemon.INSTANCE.start();
- FinalizerDaemon.INSTANCE.start();
- FinalizerWatchdogDaemon.INSTANCE.start();
- }
-
- public static void stop() {
- ReferenceQueueDaemon.INSTANCE.stop();
- FinalizerDaemon.INSTANCE.stop();
- FinalizerWatchdogDaemon.INSTANCE.stop();
- }
-
- /**
- * A background task that provides runtime support to the application.
- * Daemons can be stopped and started, but only so that the zygote can be a
- * single-threaded process when it forks.
- */
- private static abstract class Daemon implements Runnable {
- private Thread thread;
-
- public synchronized void start() {
- if (thread != null) {
- throw new IllegalStateException("already running");
- }
- thread = new Thread(ThreadGroup.mSystem, this,
- getClass().getSimpleName());
- thread.setDaemon(true);
- thread.start();
- }
-
- public abstract void run();
-
- /**
- * Returns true while the current thread should continue to run; false
- * when it should return.
- */
- protected synchronized boolean isRunning() {
- return thread != null;
- }
-
- public synchronized void interrupt() {
- if (thread == null) {
- throw new IllegalStateException("not running");
- }
- thread.interrupt();
- }
-
- /**
- * Waits for the runtime thread to stop. This interrupts the thread
- * currently running the runnable and then waits for it to exit.
- */
- public void stop() {
- Thread threadToStop;
- synchronized (this) {
- threadToStop = thread;
- thread = null;
- }
- if (threadToStop == null) {
- throw new IllegalStateException("not running");
- }
- threadToStop.interrupt();
- while (true) {
- try {
- threadToStop.join();
- return;
- } catch (InterruptedException ignored) {
- }
- }
- }
-
- /**
- * Returns the current stack trace of the thread, or an empty stack trace
- * if the thread is not currently running.
- */
- public synchronized StackTraceElement[] getStackTrace() {
- return thread != null ? thread.getStackTrace() : EmptyArray.STACK_TRACE_ELEMENT;
- }
- }
-
- /**
- * This heap management thread moves elements from the garbage collector's
- * pending list to the managed reference queue.
- */
- private static class ReferenceQueueDaemon extends Daemon {
- private static final ReferenceQueueDaemon INSTANCE = new ReferenceQueueDaemon();
-
- @Override public void run() {
- while (isRunning()) {
- Reference<?> list;
- try {
- synchronized (ReferenceQueue.class) {
- while (ReferenceQueue.unenqueued == null) {
- ReferenceQueue.class.wait();
- }
- list = ReferenceQueue.unenqueued;
- ReferenceQueue.unenqueued = null;
- }
- } catch (InterruptedException e) {
- continue;
- }
- enqueue(list);
- }
- }
-
- private void enqueue(Reference<?> list) {
- while (list != null) {
- Reference<?> reference;
- // pendingNext is owned by the GC so no synchronization is required
- if (list == list.pendingNext) {
- reference = list;
- reference.pendingNext = null;
- list = null;
- } else {
- reference = list.pendingNext;
- list.pendingNext = reference.pendingNext;
- reference.pendingNext = null;
- }
- reference.enqueueInternal();
- }
- }
- }
-
- private static class FinalizerDaemon extends Daemon {
- private static final FinalizerDaemon INSTANCE = new FinalizerDaemon();
- private final ReferenceQueue<Object> queue = FinalizerReference.queue;
- private volatile Object finalizingObject;
- private volatile long finalizingStartedNanos;
-
- @Override public void run() {
- while (isRunning()) {
- // Take a reference, blocking until one is ready or the thread should stop
- try {
- doFinalize((FinalizerReference<?>) queue.remove());
- } catch (InterruptedException ignored) {
- }
- }
- }
-
- @FindBugsSuppressWarnings("FI_EXPLICIT_INVOCATION")
- private void doFinalize(FinalizerReference<?> reference) {
- FinalizerReference.remove(reference);
- Object object = reference.get();
- reference.clear();
- try {
- finalizingStartedNanos = System.nanoTime();
- finalizingObject = object;
- synchronized (FinalizerWatchdogDaemon.INSTANCE) {
- FinalizerWatchdogDaemon.INSTANCE.notify();
- }
- object.finalize();
- } catch (Throwable ex) {
- // The RI silently swallows these, but Android has always logged.
- System.logE("Uncaught exception thrown by finalizer", ex);
- } finally {
- finalizingObject = null;
- }
- }
- }
-
- /**
- * The watchdog exits the VM if the finalizer ever gets stuck. We consider
- * the finalizer to be stuck if it spends more than MAX_FINALIZATION_MILLIS
- * on one instance.
- */
- private static class FinalizerWatchdogDaemon extends Daemon {
- private static final FinalizerWatchdogDaemon INSTANCE = new FinalizerWatchdogDaemon();
-
- @Override public void run() {
- while (isRunning()) {
- Object object = waitForObject();
- if (object == null) {
- // We have been interrupted, need to see if this daemon has been stopped.
- continue;
- }
- boolean finalized = waitForFinalization(object);
- if (!finalized && !VMRuntime.getRuntime().isDebuggerActive()) {
- finalizerTimedOut(object);
- break;
- }
- }
- }
-
- private Object waitForObject() {
- while (true) {
- Object object = FinalizerDaemon.INSTANCE.finalizingObject;
- if (object != null) {
- return object;
- }
- synchronized (this) {
- // wait until something is ready to be finalized
- // http://code.google.com/p/android/issues/detail?id=22778
- try {
- wait();
- } catch (InterruptedException e) {
- // Daemon.stop may have interrupted us.
- return null;
- }
- }
- }
- }
-
- private void sleepFor(long startNanos, long durationNanos) {
- while (true) {
- long elapsedNanos = System.nanoTime() - startNanos;
- long sleepNanos = durationNanos - elapsedNanos;
- long sleepMills = sleepNanos / NANOS_PER_MILLI;
- if (sleepMills <= 0) {
- return;
- }
- try {
- Thread.sleep(sleepMills);
- } catch (InterruptedException e) {
- if (!isRunning()) {
- return;
- }
- }
- }
- }
-
- private boolean waitForFinalization(Object object) {
- sleepFor(FinalizerDaemon.INSTANCE.finalizingStartedNanos, MAX_FINALIZE_NANOS);
- return object != FinalizerDaemon.INSTANCE.finalizingObject;
- }
-
- private static void finalizerTimedOut(Object object) {
- // The current object has exceeded the finalization deadline; abort!
- String message = object.getClass().getName() + ".finalize() timed out after "
- + (MAX_FINALIZE_NANOS / NANOS_PER_SECOND) + " seconds";
- Exception syntheticException = new TimeoutException(message);
- // We use the stack from where finalize() was running to show where it was stuck.
- syntheticException.setStackTrace(FinalizerDaemon.INSTANCE.getStackTrace());
- Thread.UncaughtExceptionHandler h = Thread.getDefaultUncaughtExceptionHandler();
- if (h == null) {
- // If we have no handler, log and exit.
- System.logE(message, syntheticException);
- System.exit(2);
- }
- // Otherwise call the handler to do crash reporting.
- // We don't just throw because we're not the thread that
- // timed out; we're the thread that detected it.
- h.uncaughtException(Thread.currentThread(), syntheticException);
- }
- }
-}
diff --git a/libdvm/src/main/java/java/lang/Enum.java b/libdvm/src/main/java/java/lang/Enum.java
deleted file mode 100644
index 4b897aa..0000000
--- a/libdvm/src/main/java/java/lang/Enum.java
+++ /dev/null
@@ -1,221 +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.lang;
-
-import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import libcore.util.BasicLruCache;
-import libcore.util.EmptyArray;
-
-/**
- * The superclass of all enumerated types. Actual enumeration types inherit from
- * this class, but extending this class does not make a class an enumeration
- * type, since the compiler needs to generate special information for it.
- */
-public abstract class Enum<E extends Enum<E>> implements Serializable, Comparable<E> {
-
- private static final long serialVersionUID = -4300926546619394005L;
-
- private static final BasicLruCache<Class<? extends Enum>, Object[]> sharedConstantsCache
- = new BasicLruCache<Class<? extends Enum>, Object[]>(64) {
- @Override protected Object[] create(Class<? extends Enum> enumType) {
- if (!enumType.isEnum()) {
- return null;
- }
- Method method = (Method) Class.getDeclaredConstructorOrMethod(
- enumType, "values", EmptyArray.CLASS);
- try {
- return (Object[]) method.invoke((Object[]) null);
- } catch (IllegalAccessException impossible) {
- throw new AssertionError();
- } catch (InvocationTargetException impossible) {
- throw new AssertionError();
- }
- }
- };
-
- private final String name;
-
- private final int ordinal;
-
- /**
- * Constructor for constants of enum subtypes.
- *
- * @param name
- * the enum constant's declared name.
- * @param ordinal
- * the enum constant's ordinal, which corresponds to its position
- * in the enum declaration, starting at zero.
- */
- protected Enum(String name, int ordinal) {
- this.name = name;
- this.ordinal = ordinal;
- }
-
- /**
- * Returns the name of this enum constant. The name is the field as it
- * appears in the {@code enum} declaration.
- *
- * @return the name of this enum constant.
- * @see #toString()
- */
- public final String name() {
- return name;
- }
-
- /**
- * Returns the position of the enum constant in the declaration. The first
- * constant has an ordinal value of zero.
- *
- * @return the ordinal value of this enum constant.
- */
- public final int ordinal() {
- return ordinal;
- }
-
- /**
- * Returns a string containing a concise, human-readable description of this
- * object. In this case, the enum constant's name is returned.
- *
- * @return a printable representation of this object.
- */
- @Override
- public String toString() {
- return name;
- }
-
- /**
- * Compares this object with the specified object and indicates if they are
- * equal. In order to be equal, {@code object} must be identical to this
- * enum constant.
- *
- * @param other
- * the object to compare this enum constant with.
- * @return {@code true} if the specified object is equal to this
- * {@code Enum}; {@code false} otherwise.
- */
- @Override
- public final boolean equals(Object other) {
- return this == other;
- }
-
- @Override
- public final int hashCode() {
- return ordinal + (name == null ? 0 : name.hashCode());
- }
-
- /**
- * {@code Enum} objects are singletons, they may not be cloned. This method
- * always throws a {@code CloneNotSupportedException}.
- *
- * @return does not return.
- * @throws CloneNotSupportedException
- * is always thrown.
- */
- @Override
- protected final Object clone() throws CloneNotSupportedException {
- throw new CloneNotSupportedException("Enums may not be cloned");
- }
-
- /**
- * Compares this object to the specified enum object to determine their
- * relative order. This method compares the object's ordinal values, that
- * is, their position in the enum declaration.
- *
- * @param o
- * the enum object to compare this object to.
- * @return a negative value if the ordinal value of this enum constant is
- * less than the ordinal value of {@code o}; 0 if the ordinal
- * values of this enum constant and {@code o} are equal; a positive
- * value if the ordinal value of this enum constant is greater than
- * the ordinal value of {@code o}.
- * @see java.lang.Comparable
- */
- public final int compareTo(E o) {
- return ordinal - o.ordinal();
- }
-
- /**
- * Returns the enum constant's declaring class.
- *
- * @return the class object representing the constant's enum type.
- */
- @SuppressWarnings("unchecked")
- public final Class<E> getDeclaringClass() {
- Class<?> myClass = getClass();
- Class<?> mySuperClass = myClass.getSuperclass();
- if (Enum.class == mySuperClass) {
- return (Class<E>)myClass;
- }
- return (Class<E>)mySuperClass;
- }
-
- /**
- * Returns the constant with the specified name of the specified enum type.
- *
- * @param enumType
- * the class of the enumerated type to search for the constant
- * value.
- * @param name
- * the name of the constant value to find.
- * @return the enum constant.
- * @throws NullPointerException
- * if either {@code enumType} or {@code name} are {@code null}.
- * @throws IllegalArgumentException
- * if {@code enumType} is not an enumerated type or does not
- * have a constant value called {@code name}.
- */
- public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
- if (enumType == null) {
- throw new NullPointerException("enumType == null");
- } else if (name == null) {
- throw new NullPointerException("name == null");
- }
- T[] values = getSharedConstants(enumType);
- if (values == null) {
- throw new IllegalArgumentException(enumType + " is not an enum type");
- }
- for (T value : values) {
- if (name.equals(value.name())) {
- return value;
- }
- }
- throw new IllegalArgumentException(name + " is not a constant in " + enumType.getName());
- }
-
- /**
- * Returns a shared, mutable array containing the constants of this enum. It
- * is an error to modify the returned array.
- *
- * @hide
- */
- @SuppressWarnings("unchecked") // the cache always returns the type matching enumType
- public static <T extends Enum<T>> T[] getSharedConstants(Class<T> enumType) {
- return (T[]) sharedConstantsCache.get(enumType);
- }
-
- /**
- * Enum types may not have finalizers.
- *
- * @since 1.6
- */
- @Override
- @SuppressWarnings("FinalizeDoesntCallSuperFinalize")
- protected final void finalize() {
- }
-}
diff --git a/libdvm/src/main/java/java/lang/Object.java b/libdvm/src/main/java/java/lang/Object.java
deleted file mode 100644
index d2cd2f1..0000000
--- a/libdvm/src/main/java/java/lang/Object.java
+++ /dev/null
@@ -1,443 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-/**
- * The root class of the Java class hierarchy. All non-primitive types
- * (including arrays) inherit either directly or indirectly from this class.
- *
- * <a name="writing_equals"><h4>Writing a correct {@code equals} method</h4></a>
- * <p>Follow this style to write a canonical {@code equals} method:
- * <pre>
- * // Use @Override to avoid accidental overloading.
- * @Override public boolean equals(Object o) {
- * // Return true if the objects are identical.
- * // (This is just an optimization, not required for correctness.)
- * if (this == o) {
- * return true;
- * }
- *
- * // Return false if the other object has the wrong type.
- * // This type may be an interface depending on the interface's specification.
- * if (!(o instanceof MyType)) {
- * return false;
- * }
- *
- * // Cast to the appropriate type.
- * // This will succeed because of the instanceof, and lets us access private fields.
- * MyType lhs = (MyType) o;
- *
- * // Check each field. Primitive fields, reference fields, and nullable reference
- * // fields are all treated differently.
- * return primitiveField == lhs.primitiveField &&
- * referenceField.equals(lhs.referenceField) &&
- * (nullableField == null ? lhs.nullableField == null
- * : nullableField.equals(lhs.nullableField));
- * }
- * </pre>
- * <p>If you override {@code equals}, you should also override {@code hashCode}: equal
- * instances must have equal hash codes.
- *
- * <p>See <i>Effective Java</i> item 8 for much more detail and clarification.
- *
- * <a name="writing_hashCode"><h4>Writing a correct {@code hashCode} method</h4></a>
- * <p>Follow this style to write a canonical {@code hashCode} method:
- * <pre>
- * @Override public int hashCode() {
- * // Start with a non-zero constant.
- * int result = 17;
- *
- * // Include a hash for each field.
- * result = 31 * result + (booleanField ? 1 : 0);
- *
- * result = 31 * result + byteField;
- * result = 31 * result + charField;
- * result = 31 * result + shortField;
- * result = 31 * result + intField;
- *
- * result = 31 * result + (int) (longField ^ (longField >>> 32));
- *
- * result = 31 * result + Float.floatToIntBits(floatField);
- *
- * long doubleFieldBits = Double.doubleToLongBits(doubleField);
- * result = 31 * result + (int) (doubleFieldBits ^ (doubleFieldBits >>> 32));
- *
- * result = 31 * result + Arrays.hashCode(arrayField);
- *
- * result = 31 * result + referenceField.hashCode();
- * result = 31 * result +
- * (nullableReferenceField == null ? 0
- * : nullableReferenceField.hashCode());
- *
- * return result;
- * }
- * </pre>
- *
- * <p>If you don't intend your type to be used as a hash key, don't simply rely on the default
- * {@code hashCode} implementation, because that silently and non-obviously breaks any future
- * code that does use your type as a hash key. You should throw instead:
- * <pre>
- * @Override public int hashCode() {
- * throw new UnsupportedOperationException();
- * }
- * </pre>
- *
- * <p>See <i>Effective Java</i> item 9 for much more detail and clarification.
- *
- * <a name="writing_toString"><h4>Writing a useful {@code toString} method</h4></a>
- * <p>For debugging convenience, it's common to override {@code toString} in this style:
- * <pre>
- * @Override public String toString() {
- * return getClass().getName() + "[" +
- * "primitiveField=" + primitiveField + ", " +
- * "referenceField=" + referenceField + ", " +
- * "arrayField=" + Arrays.toString(arrayField) + "]";
- * }
- * </pre>
- * <p>The set of fields to include is generally the same as those that would be tested
- * in your {@code equals} implementation.
- * <p>See <i>Effective Java</i> item 10 for much more detail and clarification.
- */
-public class Object {
- /**
- * Constructs a new instance of {@code Object}.
- */
- public Object() {
- }
-
- /**
- * Creates and returns a copy of this {@code Object}. The default
- * implementation returns a so-called "shallow" copy: It creates a new
- * instance of the same class and then copies the field values (including
- * object references) from this instance to the new instance. A "deep" copy,
- * in contrast, would also recursively clone nested objects. A subclass that
- * needs to implement this kind of cloning should call {@code super.clone()}
- * to create the new instance and then create deep copies of the nested,
- * mutable objects.
- *
- * @return a copy of this object.
- * @throws CloneNotSupportedException
- * if this object's class does not implement the {@code
- * Cloneable} interface.
- */
- protected Object clone() throws CloneNotSupportedException {
- if (!(this instanceof Cloneable)) {
- throw new CloneNotSupportedException("Class doesn't implement Cloneable");
- }
-
- return internalClone((Cloneable) this);
- }
-
- /*
- * Native helper method for cloning.
- */
- private native Object internalClone(Cloneable o);
-
- /**
- * Compares this instance with the specified object and indicates if they
- * are equal. In order to be equal, {@code o} must represent the same object
- * as this instance using a class-specific comparison. The general contract
- * is that this comparison should be reflexive, symmetric, and transitive.
- * Also, no object reference other than null is equal to null.
- *
- * <p>The default implementation returns {@code true} only if {@code this ==
- * o}. See <a href="{@docRoot}reference/java/lang/Object.html#writing_equals">Writing a correct
- * {@code equals} method</a>
- * if you intend implementing your own {@code equals} method.
- *
- * <p>The general contract for the {@code equals} and {@link
- * #hashCode()} methods is that if {@code equals} returns {@code true} for
- * any two objects, then {@code hashCode()} must return the same value for
- * these objects. This means that subclasses of {@code Object} usually
- * override either both methods or neither of them.
- *
- * @param o
- * the object to compare this instance with.
- * @return {@code true} if the specified object is equal to this {@code
- * Object}; {@code false} otherwise.
- * @see #hashCode
- */
- public boolean equals(Object o) {
- return this == o;
- }
-
- /**
- * Invoked when the garbage collector has detected that this instance is no longer reachable.
- * The default implementation does nothing, but this method can be overridden to free resources.
- *
- * <p>Note that objects that override {@code finalize} are significantly more expensive than
- * objects that don't. Finalizers may be run a long time after the object is no longer
- * reachable, depending on memory pressure, so it's a bad idea to rely on them for cleanup.
- * Note also that finalizers are run on a single VM-wide finalizer thread,
- * so doing blocking work in a finalizer is a bad idea. A finalizer is usually only necessary
- * for a class that has a native peer and needs to call a native method to destroy that peer.
- * Even then, it's better to provide an explicit {@code close} method (and implement
- * {@link java.io.Closeable}), and insist that callers manually dispose of instances. This
- * works well for something like files, but less well for something like a {@code BigInteger}
- * where typical calling code would have to deal with lots of temporaries. Unfortunately,
- * code that creates lots of temporaries is the worst kind of code from the point of view of
- * the single finalizer thread.
- *
- * <p>If you <i>must</i> use finalizers, consider at least providing your own
- * {@link java.lang.ref.ReferenceQueue} and having your own thread process that queue.
- *
- * <p>Unlike constructors, finalizers are not automatically chained. You are responsible for
- * calling {@code super.finalize()} yourself.
- *
- * <p>Uncaught exceptions thrown by finalizers are ignored and do not terminate the finalizer
- * thread.
- *
- * See <i>Effective Java</i> Item 7, "Avoid finalizers" for more.
- */
- @FindBugsSuppressWarnings("FI_EMPTY")
- protected void finalize() throws Throwable {
- }
-
- /**
- * Returns the unique instance of {@link Class} that represents this
- * object's class. Note that {@code getClass()} is a special case in that it
- * actually returns {@code Class<? extends Foo>} where {@code Foo} is the
- * erasure of the type of the expression {@code getClass()} was called upon.
- * <p>
- * As an example, the following code actually compiles, although one might
- * think it shouldn't:
- * <p>
- * <pre>{@code
- * List<Integer> l = new ArrayList<Integer>();
- * Class<? extends List> c = l.getClass();}</pre>
- *
- * @return this object's {@code Class} instance.
- */
- public final native Class<?> getClass();
-
- /**
- * Returns an integer hash code for this object. By contract, any two
- * objects for which {@link #equals} returns {@code true} must return
- * the same hash code value. This means that subclasses of {@code Object}
- * usually override both methods or neither method.
- *
- * <p>Note that hash values must not change over time unless information used in equals
- * comparisons also changes.
- *
- * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_hashCode">Writing a correct
- * {@code hashCode} method</a>
- * if you intend implementing your own {@code hashCode} method.
- *
- * @return this object's hash code.
- * @see #equals
- */
- public native int hashCode();
-
- /**
- * Causes a thread which is waiting on this object's monitor (by means of
- * calling one of the {@code wait()} methods) to be woken up. If more than
- * one thread is waiting, one of them is chosen at the discretion of the
- * VM. The chosen thread will not run immediately. The thread
- * that called {@code notify()} has to release the object's monitor first.
- * Also, the chosen thread still has to compete against other threads that
- * try to synchronize on the same object.
- *
- * <p>This method can only be invoked by a thread which owns this object's
- * monitor. A thread becomes owner of an object's monitor
- * <ul>
- * <li>by executing a synchronized method of that object;</li>
- * <li>by executing the body of a {@code synchronized} statement that
- * synchronizes on the object;</li>
- * <li>by executing a synchronized static method if the object is of type
- * {@code Class}.</li>
- * </ul>
- *
- * @see #notifyAll
- * @see #wait()
- * @see #wait(long)
- * @see #wait(long,int)
- * @see java.lang.Thread
- */
- public final native void notify();
-
- /**
- * Causes all threads which are waiting on this object's monitor (by means
- * of calling one of the {@code wait()} methods) to be woken up. The threads
- * will not run immediately. The thread that called {@code notify()} has to
- * release the object's monitor first. Also, the threads still have to
- * compete against other threads that try to synchronize on the same object.
- *
- * <p>This method can only be invoked by a thread which owns this object's
- * monitor. A thread becomes owner of an object's monitor
- * <ul>
- * <li>by executing a synchronized method of that object;</li>
- * <li>by executing the body of a {@code synchronized} statement that
- * synchronizes on the object;</li>
- * <li>by executing a synchronized static method if the object is of type
- * {@code Class}.</li>
- * </ul>
- *
- * @throws IllegalMonitorStateException
- * if the thread calling this method is not the owner of this
- * object's monitor.
- * @see #notify
- * @see #wait()
- * @see #wait(long)
- * @see #wait(long,int)
- * @see java.lang.Thread
- */
- public final native void notifyAll();
-
- /**
- * Returns a string containing a concise, human-readable description of this
- * object. Subclasses are encouraged to override this method and provide an
- * implementation that takes into account the object's type and data. The
- * default implementation is equivalent to the following expression:
- * <pre>
- * getClass().getName() + '@' + Integer.toHexString(hashCode())</pre>
- * <p>See <a href="{@docRoot}reference/java/lang/Object.html#writing_toString">Writing a useful
- * {@code toString} method</a>
- * if you intend implementing your own {@code toString} method.
- *
- * @return a printable representation of this object.
- */
- public String toString() {
- return getClass().getName() + '@' + Integer.toHexString(hashCode());
- }
-
- /**
- * Causes the calling thread to wait until another thread calls the {@code
- * notify()} or {@code notifyAll()} method of this object. This method can
- * only be invoked by a thread which owns this object's monitor; see
- * {@link #notify()} on how a thread can become the owner of a monitor.
- *
- * <p>A waiting thread can be sent {@code interrupt()} to cause it to
- * prematurely stop waiting, so {@code wait} should be called in a loop to
- * check that the condition that has been waited for has been met before
- * continuing.
- *
- * <p>While the thread waits, it gives up ownership of this object's
- * monitor. When it is notified (or interrupted), it re-acquires the monitor
- * before it starts running.
- *
- * @throws IllegalMonitorStateException
- * if the thread calling this method is not the owner of this
- * object's monitor.
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception
- * is thrown.
- * @see #notify
- * @see #notifyAll
- * @see #wait(long)
- * @see #wait(long,int)
- * @see java.lang.Thread
- */
- public final void wait() throws InterruptedException {
- wait(0, 0);
- }
-
- /**
- * Causes the calling thread to wait until another thread calls the {@code
- * notify()} or {@code notifyAll()} method of this object or until the
- * specified timeout expires. This method can only be invoked by a thread
- * which owns this object's monitor; see {@link #notify()} on how a thread
- * can become the owner of a monitor.
- *
- * <p>A waiting thread can be sent {@code interrupt()} to cause it to
- * prematurely stop waiting, so {@code wait} should be called in a loop to
- * check that the condition that has been waited for has been met before
- * continuing.
- *
- * <p>While the thread waits, it gives up ownership of this object's
- * monitor. When it is notified (or interrupted), it re-acquires the monitor
- * before it starts running.
- *
- * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
- * notified.
- *
- * @param millis
- * the maximum time to wait in milliseconds.
- * @throws IllegalArgumentException
- * if {@code millis < 0}.
- * @throws IllegalMonitorStateException
- * if the thread calling this method is not the owner of this
- * object's monitor.
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception
- * is thrown.
- * @see #notify
- * @see #notifyAll
- * @see #wait()
- * @see #wait(long,int)
- * @see java.lang.Thread
- */
- public final void wait(long millis) throws InterruptedException {
- wait(millis, 0);
- }
-
- /**
- * Causes the calling thread to wait until another thread calls the {@code
- * notify()} or {@code notifyAll()} method of this object or until the
- * specified timeout expires. This method can only be invoked by a thread
- * that owns this object's monitor; see {@link #notify()} on how a thread
- * can become the owner of a monitor.
- *
- * <p>A waiting thread can be sent {@code interrupt()} to cause it to
- * prematurely stop waiting, so {@code wait} should be called in a loop to
- * check that the condition that has been waited for has been met before
- * continuing.
- *
- * <p>While the thread waits, it gives up ownership of this object's
- * monitor. When it is notified (or interrupted), it re-acquires the monitor
- * before it starts running.
- *
- * <p>A timeout of zero means the calling thread should wait forever unless interrupted or
- * notified.
- *
- * @param millis
- * the maximum time to wait in milliseconds.
- * @param nanos
- * the fraction of a millisecond to wait, specified in
- * nanoseconds.
- * @throws IllegalArgumentException
- * if {@code millis < 0}, {@code nanos < 0} or {@code nanos >
- * 999999}.
- * @throws IllegalMonitorStateException
- * if the thread calling this method is not the owner of this
- * object's monitor.
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception
- * is thrown.
- * @see #notify
- * @see #notifyAll
- * @see #wait()
- * @see #wait(long,int)
- * @see java.lang.Thread
- */
- public final native void wait(long millis, int nanos) throws InterruptedException;
-}
diff --git a/libdvm/src/main/java/java/lang/String.java b/libdvm/src/main/java/java/lang/String.java
deleted file mode 100644
index 10a6301..0000000
--- a/libdvm/src/main/java/java/lang/String.java
+++ /dev/null
@@ -1,2075 +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.lang;
-
-import java.io.Serializable;
-import java.io.UnsupportedEncodingException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.Charsets;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Formatter;
-import java.util.Locale;
-import java.util.regex.Pattern;
-import libcore.util.EmptyArray;
-
-/**
- * An immutable sequence of characters/code units ({@code char}s). A
- * {@code String} is represented by array of UTF-16 values, such that
- * Unicode supplementary characters (code points) are stored/encoded as
- * surrogate pairs via Unicode code units ({@code char}).
- *
- * <a name="backing_array"><h3>Backing Arrays</h3></a>
- * This class is implemented using a char[]. The length of the array may exceed
- * the length of the string. For example, the string "Hello" may be backed by
- * the array {@code ['H', 'e', 'l', 'l', 'o', 'W'. 'o', 'r', 'l', 'd']} with
- * offset 0 and length 5.
- *
- * <p>Multiple strings can share the same char[] because strings are immutable.
- * The {@link #substring} method <strong>always</strong> returns a string that
- * shares the backing array of its source string. Generally this is an
- * optimization: fewer character arrays need to be allocated, and less copying
- * is necessary. But this can also lead to unwanted heap retention. Taking a
- * short substring of long string means that the long shared char[] won't be
- * garbage until both strings are garbage. This typically happens when parsing
- * small substrings out of a large input. To avoid this where necessary, call
- * {@code new String(longString.subString(...))}. The string copy constructor
- * always ensures that the backing array is no larger than necessary.
- *
- * @see StringBuffer
- * @see StringBuilder
- * @see Charset
- * @since 1.0
- */
-public final class String implements Serializable, Comparable<String>, CharSequence {
-
- private static final long serialVersionUID = -6849794470754667710L;
-
- private static final char REPLACEMENT_CHAR = (char) 0xfffd;
-
- /**
- * CaseInsensitiveComparator compares Strings ignoring the case of the
- * characters.
- */
- private static final class CaseInsensitiveComparator implements
- Comparator<String>, Serializable {
- private static final long serialVersionUID = 8575799808933029326L;
-
- /**
- * Compare the two objects to determine the relative ordering.
- *
- * @param o1
- * an Object to compare
- * @param o2
- * an Object to compare
- * @return an int < 0 if object1 is less than object2, 0 if they are
- * equal, and > 0 if object1 is greater
- *
- * @throws ClassCastException
- * if objects are not the correct type
- */
- public int compare(String o1, String o2) {
- return o1.compareToIgnoreCase(o2);
- }
- }
-
- /**
- * A comparator ignoring the case of the characters.
- */
- public static final Comparator<String> CASE_INSENSITIVE_ORDER = new CaseInsensitiveComparator();
-
- private static final char[] ASCII;
- static {
- ASCII = new char[128];
- for (int i = 0; i < ASCII.length; ++i) {
- ASCII[i] = (char) i;
- }
- }
-
- private final char[] value;
-
- private final int offset;
-
- private final int count;
-
- private int hashCode;
-
- /**
- * Creates an empty string.
- */
- public String() {
- value = EmptyArray.CHAR;
- offset = 0;
- count = 0;
- }
-
- /*
- * Private constructor used for JIT optimization.
- */
- @SuppressWarnings("unused")
- private String(String s, char c) {
- offset = 0;
- value = new char[s.count + 1];
- count = s.count + 1;
- System.arraycopy(s.value, s.offset, value, 0, s.count);
- value[s.count] = c;
- }
-
- /**
- * Converts the byte array to a string using the system's
- * {@link java.nio.charset.Charset#defaultCharset default charset}.
- */
- @FindBugsSuppressWarnings("DM_DEFAULT_ENCODING")
- public String(byte[] data) {
- this(data, 0, data.length);
- }
-
- /**
- * Converts the byte array to a string, setting the high byte of every
- * character to the specified value.
- *
- * @param data
- * the byte array to convert to a string.
- * @param high
- * the high byte to use.
- * @throws NullPointerException
- * if {@code data == null}.
- * @deprecated Use {@link #String(byte[])} or {@link #String(byte[], String)} instead.
- */
- @Deprecated
- public String(byte[] data, int high) {
- this(data, high, 0, data.length);
- }
-
- /**
- * Converts a subsequence of the byte array to a string using the system's
- * {@link java.nio.charset.Charset#defaultCharset default charset}.
- *
- * @throws NullPointerException
- * if {@code data == null}.
- * @throws IndexOutOfBoundsException
- * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
- */
- public String(byte[] data, int offset, int byteCount) {
- this(data, offset, byteCount, Charset.defaultCharset());
- }
-
- /**
- * Converts the byte array to a string, setting the high byte of every
- * character to {@code high}.
- *
- * @throws NullPointerException
- * if {@code data == null}.
- * @throws IndexOutOfBoundsException
- * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
- *
- * @deprecated Use {@link #String(byte[], int, int)} instead.
- */
- @Deprecated
- public String(byte[] data, int high, int offset, int byteCount) {
- if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
- throw failedBoundsCheck(data.length, offset, byteCount);
- }
- this.offset = 0;
- this.value = new char[byteCount];
- this.count = byteCount;
- high <<= 8;
- for (int i = 0; i < count; i++) {
- value[i] = (char) (high + (data[offset++] & 0xff));
- }
- }
-
- /**
- * Converts the byte array to a string using the named charset.
- *
- * <p>The behavior when the bytes cannot be decoded by the named charset
- * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
- *
- * @throws NullPointerException
- * if {@code data == null}.
- * @throws IndexOutOfBoundsException
- * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}.
- * @throws UnsupportedEncodingException
- * if the named charset is not supported.
- */
- public String(byte[] data, int offset, int byteCount, String charsetName) throws UnsupportedEncodingException {
- this(data, offset, byteCount, Charset.forNameUEE(charsetName));
- }
-
- /**
- * Converts the byte array to a string using the named charset.
- *
- * <p>The behavior when the bytes cannot be decoded by the named charset
- * is unspecified. Use {@link java.nio.charset.CharsetDecoder} for more control.
- *
- * @throws NullPointerException
- * if {@code data == null}.
- * @throws UnsupportedEncodingException
- * if {@code charsetName} is not supported.
- */
- public String(byte[] data, String charsetName) throws UnsupportedEncodingException {
- this(data, 0, data.length, Charset.forNameUEE(charsetName));
- }
-
- /**
- * Converts the byte array to a string using the given charset.
- *
- * <p>The behavior when the bytes cannot be decoded by the given charset
- * is to replace malformed input and unmappable characters with the charset's default
- * replacement string. Use {@link java.nio.charset.CharsetDecoder} for more control.
- *
- * @throws IndexOutOfBoundsException
- * if {@code byteCount < 0 || offset < 0 || offset + byteCount > data.length}
- * @throws NullPointerException
- * if {@code data == null}
- *
- * @since 1.6
- */
- public String(byte[] data, int offset, int byteCount, Charset charset) {
- if ((offset | byteCount) < 0 || byteCount > data.length - offset) {
- throw failedBoundsCheck(data.length, offset, byteCount);
- }
-
- // We inline UTF-8, ISO-8859-1, and US-ASCII decoders for speed and because 'count' and
- // 'value' are final.
- String canonicalCharsetName = charset.name();
- if (canonicalCharsetName.equals("UTF-8")) {
- byte[] d = data;
- char[] v = new char[byteCount];
-
- int idx = offset;
- int last = offset + byteCount;
- int s = 0;
-outer:
- while (idx < last) {
- byte b0 = d[idx++];
- if ((b0 & 0x80) == 0) {
- // 0xxxxxxx
- // Range: U-00000000 - U-0000007F
- int val = b0 & 0xff;
- v[s++] = (char) val;
- } else if (((b0 & 0xe0) == 0xc0) || ((b0 & 0xf0) == 0xe0) ||
- ((b0 & 0xf8) == 0xf0) || ((b0 & 0xfc) == 0xf8) || ((b0 & 0xfe) == 0xfc)) {
- int utfCount = 1;
- if ((b0 & 0xf0) == 0xe0) utfCount = 2;
- else if ((b0 & 0xf8) == 0xf0) utfCount = 3;
- else if ((b0 & 0xfc) == 0xf8) utfCount = 4;
- else if ((b0 & 0xfe) == 0xfc) utfCount = 5;
-
- // 110xxxxx (10xxxxxx)+
- // Range: U-00000080 - U-000007FF (count == 1)
- // Range: U-00000800 - U-0000FFFF (count == 2)
- // Range: U-00010000 - U-001FFFFF (count == 3)
- // Range: U-00200000 - U-03FFFFFF (count == 4)
- // Range: U-04000000 - U-7FFFFFFF (count == 5)
-
- if (idx + utfCount > last) {
- v[s++] = REPLACEMENT_CHAR;
- continue;
- }
-
- // Extract usable bits from b0
- int val = b0 & (0x1f >> (utfCount - 1));
- for (int i = 0; i < utfCount; ++i) {
- byte b = d[idx++];
- if ((b & 0xc0) != 0x80) {
- v[s++] = REPLACEMENT_CHAR;
- idx--; // Put the input char back
- continue outer;
- }
- // Push new bits in from the right side
- val <<= 6;
- val |= b & 0x3f;
- }
-
- // Note: Java allows overlong char
- // specifications To disallow, check that val
- // is greater than or equal to the minimum
- // value for each count:
- //
- // count min value
- // ----- ----------
- // 1 0x80
- // 2 0x800
- // 3 0x10000
- // 4 0x200000
- // 5 0x4000000
-
- // Allow surrogate values (0xD800 - 0xDFFF) to
- // be specified using 3-byte UTF values only
- if ((utfCount != 2) && (val >= 0xD800) && (val <= 0xDFFF)) {
- v[s++] = REPLACEMENT_CHAR;
- continue;
- }
-
- // Reject chars greater than the Unicode maximum of U+10FFFF.
- if (val > 0x10FFFF) {
- v[s++] = REPLACEMENT_CHAR;
- continue;
- }
-
- // Encode chars from U+10000 up as surrogate pairs
- if (val < 0x10000) {
- v[s++] = (char) val;
- } else {
- int x = val & 0xffff;
- int u = (val >> 16) & 0x1f;
- int w = (u - 1) & 0xffff;
- int hi = 0xd800 | (w << 6) | (x >> 10);
- int lo = 0xdc00 | (x & 0x3ff);
- v[s++] = (char) hi;
- v[s++] = (char) lo;
- }
- } else {
- // Illegal values 0x8*, 0x9*, 0xa*, 0xb*, 0xfd-0xff
- v[s++] = REPLACEMENT_CHAR;
- }
- }
-
- if (s == byteCount) {
- // We guessed right, so we can use our temporary array as-is.
- this.offset = 0;
- this.value = v;
- this.count = s;
- } else {
- // Our temporary array was too big, so reallocate and copy.
- this.offset = 0;
- this.value = new char[s];
- this.count = s;
- System.arraycopy(v, 0, value, 0, s);
- }
- } else if (canonicalCharsetName.equals("ISO-8859-1")) {
- this.offset = 0;
- this.value = new char[byteCount];
- this.count = byteCount;
- Charsets.isoLatin1BytesToChars(data, offset, byteCount, value);
- } else if (canonicalCharsetName.equals("US-ASCII")) {
- this.offset = 0;
- this.value = new char[byteCount];
- this.count = byteCount;
- Charsets.asciiBytesToChars(data, offset, byteCount, value);
- } else {
- CharBuffer cb = charset.decode(ByteBuffer.wrap(data, offset, byteCount));
- this.offset = 0;
- this.count = cb.length();
- if (count > 0) {
- // We could use cb.array() directly, but that would mean we'd have to trust
- // the CharsetDecoder doesn't hang on to the CharBuffer and mutate it later,
- // which would break String's immutability guarantee. It would also tend to
- // mean that we'd be wasting memory because CharsetDecoder doesn't trim the
- // array. So we copy.
- this.value = new char[count];
- System.arraycopy(cb.array(), 0, value, 0, count);
- } else {
- this.value = EmptyArray.CHAR;
- }
- }
- }
-
- /**
- * Converts the byte array to a String using the given charset.
- *
- * @throws NullPointerException if {@code data == null}
- * @since 1.6
- */
- public String(byte[] data, Charset charset) {
- this(data, 0, data.length, charset);
- }
-
- /**
- * Initializes this string to contain the characters in the specified
- * character array. Modifying the character array after creating the string
- * has no effect on the string.
- *
- * @throws NullPointerException if {@code data == null}
- */
- public String(char[] data) {
- this(data, 0, data.length);
- }
-
- /**
- * Initializes this string to contain the specified characters in the
- * character array. Modifying the character array after creating the string
- * has no effect on the string.
- *
- * @throws NullPointerException
- * if {@code data == null}.
- * @throws IndexOutOfBoundsException
- * if {@code charCount < 0 || offset < 0 || offset + charCount > data.length}
- */
- public String(char[] data, int offset, int charCount) {
- if ((offset | charCount) < 0 || charCount > data.length - offset) {
- throw failedBoundsCheck(data.length, offset, charCount);
- }
- this.offset = 0;
- this.value = new char[charCount];
- this.count = charCount;
- System.arraycopy(data, offset, value, 0, count);
- }
-
- /*
- * Internal version of the String(char[], int, int) constructor.
- * Does not range check, null check, or copy the character array.
- */
- String(int offset, int charCount, char[] chars) {
- this.value = chars;
- this.offset = offset;
- this.count = charCount;
- }
-
- /**
- * Constructs a new string with the same sequence of characters as {@code
- * toCopy}. The returned string's <a href="#backing_array">backing array</a>
- * is no larger than necessary.
- */
- public String(String toCopy) {
- value = (toCopy.value.length == toCopy.count)
- ? toCopy.value
- : Arrays.copyOfRange(toCopy.value, toCopy.offset, toCopy.offset + toCopy.length());
- offset = 0;
- count = value.length;
- }
-
- /*
- * Private constructor useful for JIT optimization.
- */
- @SuppressWarnings( { "unused", "nls" })
- private String(String s1, String s2) {
- if (s1 == null) {
- s1 = "null";
- }
- if (s2 == null) {
- s2 = "null";
- }
- count = s1.count + s2.count;
- value = new char[count];
- offset = 0;
- System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
- System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
- }
-
- /*
- * Private constructor useful for JIT optimization.
- */
- @SuppressWarnings( { "unused", "nls" })
- private String(String s1, String s2, String s3) {
- if (s1 == null) {
- s1 = "null";
- }
- if (s2 == null) {
- s2 = "null";
- }
- if (s3 == null) {
- s3 = "null";
- }
- count = s1.count + s2.count + s3.count;
- value = new char[count];
- offset = 0;
- System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
- System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
- System.arraycopy(s3.value, s3.offset, value, s1.count + s2.count, s3.count);
- }
-
- /**
- * Creates a {@code String} from the contents of the specified
- * {@code StringBuffer}.
- */
- public String(StringBuffer stringBuffer) {
- offset = 0;
- synchronized (stringBuffer) {
- value = stringBuffer.shareValue();
- count = stringBuffer.length();
- }
- }
-
- /**
- * Creates a {@code String} from the sub-array of Unicode code points.
- *
- * @throws NullPointerException
- * if {@code codePoints == null}.
- * @throws IllegalArgumentException
- * if any of the elements of {@code codePoints} are not valid
- * Unicode code points.
- * @throws IndexOutOfBoundsException
- * if {@code offset} or {@code count} are not within the bounds
- * of {@code codePoints}.
- * @since 1.5
- */
- public String(int[] codePoints, int offset, int count) {
- if (codePoints == null) {
- throw new NullPointerException("codePoints == null");
- }
- if ((offset | count) < 0 || count > codePoints.length - offset) {
- throw failedBoundsCheck(codePoints.length, offset, count);
- }
- this.offset = 0;
- this.value = new char[count * 2];
- int end = offset + count;
- int c = 0;
- for (int i = offset; i < end; i++) {
- c += Character.toChars(codePoints[i], this.value, c);
- }
- this.count = c;
- }
-
- /**
- * Creates a {@code String} from the contents of the specified {@code
- * StringBuilder}.
- *
- * @throws NullPointerException
- * if {@code stringBuilder == null}.
- * @since 1.5
- */
- public String(StringBuilder stringBuilder) {
- if (stringBuilder == null) {
- throw new NullPointerException("stringBuilder == null");
- }
- this.offset = 0;
- this.count = stringBuilder.length();
- this.value = new char[this.count];
- stringBuilder.getChars(0, this.count, this.value, 0);
- }
-
- /*
- * Creates a {@code String} that is s1 + v1. May be used by JIT code.
- */
- @SuppressWarnings("unused")
- private String(String s1, int v1) {
- if (s1 == null) {
- s1 = "null";
- }
- String s2 = String.valueOf(v1);
- int len = s1.count + s2.count;
- value = new char[len];
- offset = 0;
- System.arraycopy(s1.value, s1.offset, value, 0, s1.count);
- System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count);
- count = len;
- }
-
- /**
- * Returns the character at {@code index}.
- * @throws IndexOutOfBoundsException if {@code index < 0} or {@code index >= length()}.
- */
- public char charAt(int index) {
- if (index < 0 || index >= count) {
- throw indexAndLength(index);
- }
- return value[offset + index];
- }
-
- private StringIndexOutOfBoundsException indexAndLength(int index) {
- throw new StringIndexOutOfBoundsException(this, index);
- }
-
- private StringIndexOutOfBoundsException startEndAndLength(int start, int end) {
- throw new StringIndexOutOfBoundsException(this, start, end - start);
- }
-
- private StringIndexOutOfBoundsException failedBoundsCheck(int arrayLength, int offset, int count) {
- throw new StringIndexOutOfBoundsException(arrayLength, offset, count);
- }
-
- /**
- * This isn't equivalent to either of ICU's u_foldCase case folds, and thus any of the Unicode
- * case folds, but it's what the RI uses.
- */
- private char foldCase(char ch) {
- if (ch < 128) {
- if ('A' <= ch && ch <= 'Z') {
- return (char) (ch + ('a' - 'A'));
- }
- return ch;
- }
- return Character.toLowerCase(Character.toUpperCase(ch));
- }
-
- /**
- * Compares the specified string to this string using the Unicode values of
- * the characters. Returns 0 if the strings contain the same characters in
- * the same order. Returns a negative integer if the first non-equal
- * character in this string has a Unicode value which is less than the
- * Unicode value of the character at the same position in the specified
- * string, or if this string is a prefix of the specified string. Returns a
- * positive integer if the first non-equal character in this string has a
- * Unicode value which is greater than the Unicode value of the character at
- * the same position in the specified string, or if the specified string is
- * a prefix of this string.
- *
- * @param string
- * the string to compare.
- * @return 0 if the strings are equal, a negative integer if this string is
- * before the specified string, or a positive integer if this string
- * is after the specified string.
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public native int compareTo(String string);
-
- /**
- * Compares the specified string to this string using the Unicode values of
- * the characters, ignoring case differences. Returns 0 if the strings
- * contain the same characters in the same order. Returns a negative integer
- * if the first non-equal character in this string has a Unicode value which
- * is less than the Unicode value of the character at the same position in
- * the specified string, or if this string is a prefix of the specified
- * string. Returns a positive integer if the first non-equal character in
- * this string has a Unicode value which is greater than the Unicode value
- * of the character at the same position in the specified string, or if the
- * specified string is a prefix of this string.
- *
- * @param string
- * the string to compare.
- * @return 0 if the strings are equal, a negative integer if this string is
- * before the specified string, or a positive integer if this string
- * is after the specified string.
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public int compareToIgnoreCase(String string) {
- int o1 = offset, o2 = string.offset, result;
- int end = offset + (count < string.count ? count : string.count);
- char c1, c2;
- char[] target = string.value;
- while (o1 < end) {
- if ((c1 = value[o1++]) == (c2 = target[o2++])) {
- continue;
- }
- c1 = foldCase(c1);
- c2 = foldCase(c2);
- if ((result = c1 - c2) != 0) {
- return result;
- }
- }
- return count - string.count;
- }
-
- /**
- * Concatenates this string and the specified string.
- *
- * @param string
- * the string to concatenate
- * @return a new string which is the concatenation of this string and the
- * specified string.
- */
- public String concat(String string) {
- if (string.count > 0 && count > 0) {
- char[] buffer = new char[count + string.count];
- System.arraycopy(value, offset, buffer, 0, count);
- System.arraycopy(string.value, string.offset, buffer, count, string.count);
- return new String(0, buffer.length, buffer);
- }
- return count == 0 ? string : this;
- }
-
- /**
- * Creates a new string containing the characters in the specified character
- * array. Modifying the character array after creating the string has no
- * effect on the string.
- *
- * @param data
- * the array of characters.
- * @return the new string.
- * @throws NullPointerException
- * if {@code data} is {@code null}.
- */
- public static String copyValueOf(char[] data) {
- return new String(data, 0, data.length);
- }
-
- /**
- * Creates a new string containing the specified characters in the character
- * array. Modifying the character array after creating the string has no
- * effect on the string.
- *
- * @param data
- * the array of characters.
- * @param start
- * the starting offset in the character array.
- * @param length
- * the number of characters to use.
- * @return the new string.
- * @throws NullPointerException
- * if {@code data} is {@code null}.
- * @throws IndexOutOfBoundsException
- * if {@code length < 0, start < 0} or {@code start + length >
- * data.length}.
- */
- public static String copyValueOf(char[] data, int start, int length) {
- return new String(data, start, length);
- }
-
- /**
- * Compares the specified string to this string to determine if the
- * specified string is a suffix.
- *
- * @param suffix
- * the suffix to look for.
- * @return {@code true} if the specified string is a suffix of this string,
- * {@code false} otherwise.
- * @throws NullPointerException
- * if {@code suffix} is {@code null}.
- */
- public boolean endsWith(String suffix) {
- return regionMatches(count - suffix.count, suffix, 0, suffix.count);
- }
-
- /**
- * Compares the specified object to this string and returns true if they are
- * equal. The object must be an instance of string with the same characters
- * in the same order.
- *
- * @param other
- * the object to compare.
- * @return {@code true} if the specified object is equal to this string,
- * {@code false} otherwise.
- * @see #hashCode
- */
- @Override public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
- if (other instanceof String) {
- String s = (String)other;
- int count = this.count;
- if (s.count != count) {
- return false;
- }
- // TODO: we want to avoid many boundchecks in the loop below
- // for long Strings until we have array equality intrinsic.
- // Bad benchmarks just push .equals without first getting a
- // hashCode hit (unlike real world use in a Hashtable). Filter
- // out these long strings here. When we get the array equality
- // intrinsic then remove this use of hashCode.
- if (hashCode() != s.hashCode()) {
- return false;
- }
- char[] value1 = value;
- int offset1 = offset;
- char[] value2 = s.value;
- int offset2 = s.offset;
- for (int end = offset1 + count; offset1 < end; ) {
- if (value1[offset1] != value2[offset2]) {
- return false;
- }
- offset1++;
- offset2++;
- }
- return true;
- } else {
- return false;
- }
- }
-
- /**
- * Compares the specified string to this string ignoring the case of the
- * characters and returns true if they are equal.
- *
- * @param string
- * the string to compare.
- * @return {@code true} if the specified string is equal to this string,
- * {@code false} otherwise.
- */
- @FindBugsSuppressWarnings("ES_COMPARING_PARAMETER_STRING_WITH_EQ")
- public boolean equalsIgnoreCase(String string) {
- if (string == this) {
- return true;
- }
- if (string == null || count != string.count) {
- return false;
- }
- int o1 = offset, o2 = string.offset;
- int end = offset + count;
- char[] target = string.value;
- while (o1 < end) {
- char c1 = value[o1++];
- char c2 = target[o2++];
- if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Mangles this string into a byte array by stripping the high order bits from
- * each character. Use {@link #getBytes()} or {@link #getBytes(String)} instead.
- *
- * @param start
- * the starting offset of characters to copy.
- * @param end
- * the ending offset of characters to copy.
- * @param data
- * the destination byte array.
- * @param index
- * the starting offset in the destination byte array.
- * @throws NullPointerException
- * if {@code data} is {@code null}.
- * @throws IndexOutOfBoundsException
- * if {@code start < 0}, {@code end > length()}, {@code index <
- * 0} or {@code end - start > data.length - index}.
- * @deprecated Use {@link #getBytes()} or {@link #getBytes(String)} instead.
- */
- @Deprecated
- public void getBytes(int start, int end, byte[] data, int index) {
- // Note: last character not copied!
- if (start >= 0 && start <= end && end <= count) {
- end += offset;
- try {
- for (int i = offset + start; i < end; i++) {
- data[index++] = (byte) value[i];
- }
- } catch (ArrayIndexOutOfBoundsException ignored) {
- throw failedBoundsCheck(data.length, index, end - start);
- }
- } else {
- throw startEndAndLength(start, end);
- }
- }
-
- /**
- * Returns a new byte array containing the characters of this string encoded using the
- * system's {@link java.nio.charset.Charset#defaultCharset default charset}.
- *
- * <p>The behavior when this string cannot be represented in the system's default charset
- * is unspecified. In practice, when the default charset is UTF-8 (as it is on Android),
- * all strings can be encoded.
- */
- public byte[] getBytes() {
- return getBytes(Charset.defaultCharset());
- }
-
- /**
- * Returns a new byte array containing the characters of this string encoded using the
- * named charset.
- *
- * <p>The behavior when this string cannot be represented in the named charset
- * is unspecified. Use {@link java.nio.charset.CharsetEncoder} for more control.
- *
- * @throws UnsupportedEncodingException if the charset is not supported
- */
- public byte[] getBytes(String charsetName) throws UnsupportedEncodingException {
- return getBytes(Charset.forNameUEE(charsetName));
- }
-
- /**
- * Returns a new byte array containing the characters of this string encoded using the
- * given charset.
- *
- * <p>The behavior when this string cannot be represented in the given charset
- * is to replace malformed input and unmappable characters with the charset's default
- * replacement byte array. Use {@link java.nio.charset.CharsetEncoder} for more control.
- *
- * @since 1.6
- */
- public byte[] getBytes(Charset charset) {
- String canonicalCharsetName = charset.name();
- if (canonicalCharsetName.equals("UTF-8")) {
- return Charsets.toUtf8Bytes(value, offset, count);
- } else if (canonicalCharsetName.equals("ISO-8859-1")) {
- return Charsets.toIsoLatin1Bytes(value, offset, count);
- } else if (canonicalCharsetName.equals("US-ASCII")) {
- return Charsets.toAsciiBytes(value, offset, count);
- } else if (canonicalCharsetName.equals("UTF-16BE")) {
- return Charsets.toBigEndianUtf16Bytes(value, offset, count);
- } else {
- CharBuffer chars = CharBuffer.wrap(this.value, this.offset, this.count);
- ByteBuffer buffer = charset.encode(chars.asReadOnlyBuffer());
- byte[] bytes = new byte[buffer.limit()];
- buffer.get(bytes);
- return bytes;
- }
- }
-
- /**
- * Copies the specified characters in this string to the character array
- * starting at the specified offset in the character array.
- *
- * @param start
- * the starting offset of characters to copy.
- * @param end
- * the ending offset of characters to copy.
- * @param buffer
- * the destination character array.
- * @param index
- * the starting offset in the character array.
- * @throws NullPointerException
- * if {@code buffer} is {@code null}.
- * @throws IndexOutOfBoundsException
- * if {@code start < 0}, {@code end > length()}, {@code start >
- * end}, {@code index < 0}, {@code end - start > buffer.length -
- * index}
- */
- public void getChars(int start, int end, char[] buffer, int index) {
- // Note: last character not copied!
- if (start >= 0 && start <= end && end <= count) {
- System.arraycopy(value, start + offset, buffer, index, end - start);
- } else {
- // We throw StringIndexOutOfBoundsException rather than System.arraycopy's AIOOBE.
- throw startEndAndLength(start, end);
- }
- }
-
- /**
- * Version of getChars without bounds checks, for use by other classes
- * within the java.lang package only. The caller is responsible for
- * ensuring that start >= 0 && start <= end && end <= count.
- */
- void _getChars(int start, int end, char[] buffer, int index) {
- // NOTE last character not copied!
- System.arraycopy(value, start + offset, buffer, index, end - start);
- }
-
- @Override public int hashCode() {
- int hash = hashCode;
- if (hash == 0) {
- if (count == 0) {
- return 0;
- }
- final int end = count + offset;
- final char[] chars = value;
- for (int i = offset; i < end; ++i) {
- hash = 31*hash + chars[i];
- }
- hashCode = hash;
- }
- return hash;
- }
-
- /**
- * Searches in this string for the first index of the specified character.
- * The search for the character starts at the beginning and moves towards
- * the end of this string.
- *
- * @param c
- * the character to find.
- * @return the index in this string of the specified character, -1 if the
- * character isn't found.
- */
- public int indexOf(int c) {
- // TODO: just "return indexOf(c, 0);" when the JIT can inline that deep.
- if (c > 0xffff) {
- return indexOfSupplementary(c, 0);
- }
- return fastIndexOf(c, 0);
- }
-
- /**
- * Searches in this string for the index of the specified character. The
- * search for the character starts at the specified offset and moves towards
- * the end of this string.
- *
- * @param c
- * the character to find.
- * @param start
- * the starting offset.
- * @return the index in this string of the specified character, -1 if the
- * character isn't found.
- */
- public int indexOf(int c, int start) {
- if (c > 0xffff) {
- return indexOfSupplementary(c, start);
- }
- return fastIndexOf(c, start);
- }
-
- private native int fastIndexOf(int c, int start);
-
- private int indexOfSupplementary(int c, int start) {
- if (!Character.isSupplementaryCodePoint(c)) {
- return -1;
- }
- char[] chars = Character.toChars(c);
- String needle = new String(0, chars.length, chars);
- return indexOf(needle, start);
- }
-
- /**
- * Searches in this string for the first index of the specified string. The
- * search for the string starts at the beginning and moves towards the end
- * of this string.
- *
- * @param string
- * the string to find.
- * @return the index of the first character of the specified string in this
- * string, -1 if the specified string is not a substring.
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public int indexOf(String string) {
- int start = 0;
- int subCount = string.count;
- int _count = count;
- if (subCount > 0) {
- if (subCount > _count) {
- return -1;
- }
- char[] target = string.value;
- int subOffset = string.offset;
- char firstChar = target[subOffset];
- int end = subOffset + subCount;
- while (true) {
- int i = indexOf(firstChar, start);
- if (i == -1 || subCount + i > _count) {
- return -1; // handles subCount > count || start >= count
- }
- int o1 = offset + i, o2 = subOffset;
- char[] _value = value;
- while (++o2 < end && _value[++o1] == target[o2]) {
- // Intentionally empty
- }
- if (o2 == end) {
- return i;
- }
- start = i + 1;
- }
- }
- return start < _count ? start : _count;
- }
-
- /**
- * Searches in this string for the index of the specified string. The search
- * for the string starts at the specified offset and moves towards the end
- * of this string.
- *
- * @param subString
- * the string to find.
- * @param start
- * the starting offset.
- * @return the index of the first character of the specified string in this
- * string, -1 if the specified string is not a substring.
- * @throws NullPointerException
- * if {@code subString} is {@code null}.
- */
- public int indexOf(String subString, int start) {
- if (start < 0) {
- start = 0;
- }
- int subCount = subString.count;
- int _count = count;
- if (subCount > 0) {
- if (subCount + start > _count) {
- return -1;
- }
- char[] target = subString.value;
- int subOffset = subString.offset;
- char firstChar = target[subOffset];
- int end = subOffset + subCount;
- while (true) {
- int i = indexOf(firstChar, start);
- if (i == -1 || subCount + i > _count) {
- return -1; // handles subCount > count || start >= count
- }
- int o1 = offset + i, o2 = subOffset;
- char[] _value = value;
- while (++o2 < end && _value[++o1] == target[o2]) {
- // Intentionally empty
- }
- if (o2 == end) {
- return i;
- }
- start = i + 1;
- }
- }
- return start < _count ? start : _count;
- }
-
- /**
- * Returns an interned string equal to this string. The VM maintains an internal set of
- * unique strings. All string literals found in loaded classes'
- * constant pools are automatically interned. Manually-interned strings are only weakly
- * referenced, so calling {@code intern} won't lead to unwanted retention.
- *
- * <p>Interning is typically used because it guarantees that for interned strings
- * {@code a} and {@code b}, {@code a.equals(b)} can be simplified to
- * {@code a == b}. (This is not true of non-interned strings.)
- *
- * <p>Many applications find it simpler and more convenient to use an explicit
- * {@link java.util.HashMap} to implement their own pools.
- */
- public native String intern();
-
- /**
- * Returns true if the length of this string is 0.
- *
- * @since 1.6
- */
- public boolean isEmpty() {
- return count == 0;
- }
-
- /**
- * Returns the last index of the code point {@code c}, or -1.
- * The search for the character starts at the end and moves towards the
- * beginning of this string.
- */
- public int lastIndexOf(int c) {
- if (c > 0xffff) {
- return lastIndexOfSupplementary(c, Integer.MAX_VALUE);
- }
- int _count = count;
- int _offset = offset;
- char[] _value = value;
- for (int i = _offset + _count - 1; i >= _offset; --i) {
- if (_value[i] == c) {
- return i - _offset;
- }
- }
- return -1;
- }
-
- /**
- * Returns the last index of the code point {@code c}, or -1.
- * The search for the character starts at offset {@code start} and moves towards
- * the beginning of this string.
- */
- public int lastIndexOf(int c, int start) {
- if (c > 0xffff) {
- return lastIndexOfSupplementary(c, start);
- }
- int _count = count;
- int _offset = offset;
- char[] _value = value;
- if (start >= 0) {
- if (start >= _count) {
- start = _count - 1;
- }
- for (int i = _offset + start; i >= _offset; --i) {
- if (_value[i] == c) {
- return i - _offset;
- }
- }
- }
- return -1;
- }
-
- private int lastIndexOfSupplementary(int c, int start) {
- if (!Character.isSupplementaryCodePoint(c)) {
- return -1;
- }
- char[] chars = Character.toChars(c);
- String needle = new String(0, chars.length, chars);
- return lastIndexOf(needle, start);
- }
-
- /**
- * Searches in this string for the last index of the specified string. The
- * search for the string starts at the end and moves towards the beginning
- * of this string.
- *
- * @param string
- * the string to find.
- * @return the index of the first character of the specified string in this
- * string, -1 if the specified string is not a substring.
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public int lastIndexOf(String string) {
- // Use count instead of count - 1 so lastIndexOf("") returns count
- return lastIndexOf(string, count);
- }
-
- /**
- * Searches in this string for the index of the specified string. The search
- * for the string starts at the specified offset and moves towards the
- * beginning of this string.
- *
- * @param subString
- * the string to find.
- * @param start
- * the starting offset.
- * @return the index of the first character of the specified string in this
- * string , -1 if the specified string is not a substring.
- * @throws NullPointerException
- * if {@code subString} is {@code null}.
- */
- public int lastIndexOf(String subString, int start) {
- int subCount = subString.count;
- if (subCount <= count && start >= 0) {
- if (subCount > 0) {
- if (start > count - subCount) {
- start = count - subCount;
- }
- // count and subCount are both >= 1
- char[] target = subString.value;
- int subOffset = subString.offset;
- char firstChar = target[subOffset];
- int end = subOffset + subCount;
- while (true) {
- int i = lastIndexOf(firstChar, start);
- if (i == -1) {
- return -1;
- }
- int o1 = offset + i, o2 = subOffset;
- while (++o2 < end && value[++o1] == target[o2]) {
- // Intentionally empty
- }
- if (o2 == end) {
- return i;
- }
- start = i - 1;
- }
- }
- return start < count ? start : count;
- }
- return -1;
- }
-
- /**
- * Returns the number of characters in this string.
- */
- public int length() {
- return count;
- }
-
- /**
- * Compares the specified string to this string and compares the specified
- * range of characters to determine if they are the same.
- *
- * @param thisStart
- * the starting offset in this string.
- * @param string
- * the string to compare.
- * @param start
- * the starting offset in the specified string.
- * @param length
- * the number of characters to compare.
- * @return {@code true} if the ranges of characters are equal, {@code false}
- * otherwise
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public boolean regionMatches(int thisStart, String string, int start, int length) {
- if (string == null) {
- throw new NullPointerException("string == null");
- }
- if (start < 0 || string.count - start < length) {
- return false;
- }
- if (thisStart < 0 || count - thisStart < length) {
- return false;
- }
- if (length <= 0) {
- return true;
- }
- int o1 = offset + thisStart, o2 = string.offset + start;
- char[] value1 = value;
- char[] value2 = string.value;
- for (int i = 0; i < length; ++i) {
- if (value1[o1 + i] != value2[o2 + i]) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Compares the specified string to this string and compares the specified
- * range of characters to determine if they are the same. When ignoreCase is
- * true, the case of the characters is ignored during the comparison.
- *
- * @param ignoreCase
- * specifies if case should be ignored.
- * @param thisStart
- * the starting offset in this string.
- * @param string
- * the string to compare.
- * @param start
- * the starting offset in the specified string.
- * @param length
- * the number of characters to compare.
- * @return {@code true} if the ranges of characters are equal, {@code false}
- * otherwise.
- * @throws NullPointerException
- * if {@code string} is {@code null}.
- */
- public boolean regionMatches(boolean ignoreCase, int thisStart, String string, int start, int length) {
- if (!ignoreCase) {
- return regionMatches(thisStart, string, start, length);
- }
- if (string == null) {
- throw new NullPointerException("string == null");
- }
- if (thisStart < 0 || length > count - thisStart) {
- return false;
- }
- if (start < 0 || length > string.count - start) {
- return false;
- }
- thisStart += offset;
- start += string.offset;
- int end = thisStart + length;
- char[] target = string.value;
- while (thisStart < end) {
- char c1 = value[thisStart++];
- char c2 = target[start++];
- if (c1 != c2 && foldCase(c1) != foldCase(c2)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Copies this string replacing occurrences of the specified character with
- * another character.
- *
- * @param oldChar
- * the character to replace.
- * @param newChar
- * the replacement character.
- * @return a new string with occurrences of oldChar replaced by newChar.
- */
- public String replace(char oldChar, char newChar) {
- char[] buffer = value;
- int _offset = offset;
- int _count = count;
-
- int idx = _offset;
- int last = _offset + _count;
- boolean copied = false;
- while (idx < last) {
- if (buffer[idx] == oldChar) {
- if (!copied) {
- char[] newBuffer = new char[_count];
- System.arraycopy(buffer, _offset, newBuffer, 0, _count);
- buffer = newBuffer;
- idx -= _offset;
- last -= _offset;
- copied = true;
- }
- buffer[idx] = newChar;
- }
- idx++;
- }
-
- return copied ? new String(0, count, buffer) : this;
- }
-
- /**
- * Copies this string replacing occurrences of the specified target sequence
- * with another sequence. The string is processed from the beginning to the
- * end.
- *
- * @param target
- * the sequence to replace.
- * @param replacement
- * the replacement sequence.
- * @return the resulting string.
- * @throws NullPointerException
- * if {@code target} or {@code replacement} is {@code null}.
- */
- public String replace(CharSequence target, CharSequence replacement) {
- if (target == null) {
- throw new NullPointerException("target == null");
- }
- if (replacement == null) {
- throw new NullPointerException("replacement == null");
- }
-
- String targetString = target.toString();
- int matchStart = indexOf(targetString, 0);
- if (matchStart == -1) {
- // If there's nothing to replace, return the original string untouched.
- return this;
- }
-
- String replacementString = replacement.toString();
-
- // The empty target matches at the start and end and between each character.
- int targetLength = targetString.length();
- if (targetLength == 0) {
- // The result contains the original 'count' characters, a copy of the
- // replacement string before every one of those characters, and a final
- // copy of the replacement string at the end.
- int resultLength = count + (count + 1) * replacementString.length();
- StringBuilder result = new StringBuilder(resultLength);
- result.append(replacementString);
- int end = offset + count;
- for (int i = offset; i != end; ++i) {
- result.append(value[i]);
- result.append(replacementString);
- }
- return result.toString();
- }
-
- StringBuilder result = new StringBuilder(count);
- int searchStart = 0;
- do {
- // Copy characters before the match...
- result.append(value, offset + searchStart, matchStart - searchStart);
- // Insert the replacement...
- result.append(replacementString);
- // And skip over the match...
- searchStart = matchStart + targetLength;
- } while ((matchStart = indexOf(targetString, searchStart)) != -1);
- // Copy any trailing chars...
- result.append(value, offset + searchStart, count - searchStart);
- return result.toString();
- }
-
- /**
- * Compares the specified string to this string to determine if the
- * specified string is a prefix.
- *
- * @param prefix
- * the string to look for.
- * @return {@code true} if the specified string is a prefix of this string,
- * {@code false} otherwise
- * @throws NullPointerException
- * if {@code prefix} is {@code null}.
- */
- public boolean startsWith(String prefix) {
- return startsWith(prefix, 0);
- }
-
- /**
- * Compares the specified string to this string, starting at the specified
- * offset, to determine if the specified string is a prefix.
- *
- * @param prefix
- * the string to look for.
- * @param start
- * the starting offset.
- * @return {@code true} if the specified string occurs in this string at the
- * specified offset, {@code false} otherwise.
- * @throws NullPointerException
- * if {@code prefix} is {@code null}.
- */
- public boolean startsWith(String prefix, int start) {
- return regionMatches(start, prefix, 0, prefix.count);
- }
-
- /**
- * Returns a string containing a suffix of this string. The returned string
- * shares this string's <a href="#backing_array">backing array</a>.
- *
- * @param start
- * the offset of the first character.
- * @return a new string containing the characters from start to the end of
- * the string.
- * @throws IndexOutOfBoundsException
- * if {@code start < 0} or {@code start > length()}.
- */
- public String substring(int start) {
- if (start == 0) {
- return this;
- }
- if (start >= 0 && start <= count) {
- return new String(offset + start, count - start, value);
- }
- throw indexAndLength(start);
- }
-
- /**
- * Returns a string containing a subsequence of characters from this string.
- * The returned string shares this string's <a href="#backing_array">backing
- * array</a>.
- *
- * @param start
- * the offset of the first character.
- * @param end
- * the offset one past the last character.
- * @return a new string containing the characters from start to end - 1
- * @throws IndexOutOfBoundsException
- * if {@code start < 0}, {@code start > end} or {@code end >
- * length()}.
- */
- public String substring(int start, int end) {
- if (start == 0 && end == count) {
- return this;
- }
- // NOTE last character not copied!
- // Fast range check.
- if (start >= 0 && start <= end && end <= count) {
- return new String(offset + start, end - start, value);
- }
- throw startEndAndLength(start, end);
- }
-
- /**
- * Returns a new {@code char} array containing a copy of the characters in this string.
- * This is expensive and rarely useful. If you just want to iterate over the characters in
- * the string, use {@link #charAt} instead.
- */
- public char[] toCharArray() {
- char[] buffer = new char[count];
- System.arraycopy(value, offset, buffer, 0, count);
- return buffer;
- }
-
- /**
- * Converts this string to lower case, using the rules of the user's default locale.
- * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
- *
- * @return a new lower case string, or {@code this} if it's already all lower case.
- */
- public String toLowerCase() {
- return CaseMapper.toLowerCase(Locale.getDefault(), this, value, offset, count);
- }
-
- /**
- * Converts this string to lower case, using the rules of {@code locale}.
- *
- * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
- * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
- * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
- * correct case mapping of Greek characters: any locale will do.
- *
- * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
- * for full details of context- and language-specific special cases.
- *
- * @return a new lower case string, or {@code this} if it's already all lower case.
- */
- public String toLowerCase(Locale locale) {
- return CaseMapper.toLowerCase(locale, this, value, offset, count);
- }
-
- /**
- * Returns this string.
- */
- @Override
- public String toString() {
- return this;
- }
-
- /**
- * Converts this this string to upper case, using the rules of the user's default locale.
- * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
- *
- * @return a new upper case string, or {@code this} if it's already all upper case.
- */
- public String toUpperCase() {
- return CaseMapper.toUpperCase(Locale.getDefault(), this, value, offset, count);
- }
-
- /**
- * Converts this this string to upper case, using the rules of {@code locale}.
- *
- * <p>Most case mappings are unaffected by the language of a {@code Locale}. Exceptions include
- * dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in
- * Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get
- * correct case mapping of Greek characters: any locale will do.
- *
- * <p>See <a href="http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt">http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt</a>
- * for full details of context- and language-specific special cases.
- *
- * @return a new upper case string, or {@code this} if it's already all upper case.
- */
- public String toUpperCase(Locale locale) {
- return CaseMapper.toUpperCase(locale, this, value, offset, count);
- }
-
- /**
- * Copies this string removing white space characters from the beginning and
- * end of the string.
- *
- * @return a new string with characters <code><= \\u0020</code> removed from
- * the beginning and the end.
- */
- public String trim() {
- int start = offset, last = offset + count - 1;
- int end = last;
- while ((start <= end) && (value[start] <= ' ')) {
- start++;
- }
- while ((end >= start) && (value[end] <= ' ')) {
- end--;
- }
- if (start == offset && end == last) {
- return this;
- }
- return new String(start, end - start + 1, value);
- }
-
- /**
- * Creates a new string containing the characters in the specified character
- * array. Modifying the character array after creating the string has no
- * effect on the string.
- *
- * @param data
- * the array of characters.
- * @return the new string.
- * @throws NullPointerException
- * if {@code data} is {@code null}.
- */
- public static String valueOf(char[] data) {
- return new String(data, 0, data.length);
- }
-
- /**
- * Creates a new string containing the specified characters in the character
- * array. Modifying the character array after creating the string has no
- * effect on the string.
- *
- * @param data
- * the array of characters.
- * @param start
- * the starting offset in the character array.
- * @param length
- * the number of characters to use.
- * @return the new string.
- * @throws IndexOutOfBoundsException
- * if {@code length < 0}, {@code start < 0} or {@code start +
- * length > data.length}
- * @throws NullPointerException
- * if {@code data} is {@code null}.
- */
- public static String valueOf(char[] data, int start, int length) {
- return new String(data, start, length);
- }
-
- /**
- * Converts the specified character to its string representation.
- *
- * @param value
- * the character.
- * @return the character converted to a string.
- */
- public static String valueOf(char value) {
- String s;
- if (value < 128) {
- s = new String(value, 1, ASCII);
- } else {
- s = new String(0, 1, new char[] { value });
- }
- s.hashCode = value;
- return s;
- }
-
- /**
- * Converts the specified double to its string representation.
- *
- * @param value
- * the double.
- * @return the double converted to a string.
- */
- public static String valueOf(double value) {
- return Double.toString(value);
- }
-
- /**
- * Converts the specified float to its string representation.
- *
- * @param value
- * the float.
- * @return the float converted to a string.
- */
- public static String valueOf(float value) {
- return Float.toString(value);
- }
-
- /**
- * Converts the specified integer to its string representation.
- *
- * @param value
- * the integer.
- * @return the integer converted to a string.
- */
- public static String valueOf(int value) {
- return Integer.toString(value);
- }
-
- /**
- * Converts the specified long to its string representation.
- *
- * @param value
- * the long.
- * @return the long converted to a string.
- */
- public static String valueOf(long value) {
- return Long.toString(value);
- }
-
- /**
- * Converts the specified object to its string representation. If the object
- * is null return the string {@code "null"}, otherwise use {@code
- * toString()} to get the string representation.
- *
- * @param value
- * the object.
- * @return the object converted to a string, or the string {@code "null"}.
- */
- public static String valueOf(Object value) {
- return value != null ? value.toString() : "null";
- }
-
- /**
- * Converts the specified boolean to its string representation. When the
- * boolean is {@code true} return {@code "true"}, otherwise return {@code
- * "false"}.
- *
- * @param value
- * the boolean.
- * @return the boolean converted to a string.
- */
- public static String valueOf(boolean value) {
- return value ? "true" : "false";
- }
-
- /**
- * Returns whether the characters in the StringBuffer {@code strbuf} are the
- * same as those in this string.
- *
- * @param strbuf
- * the StringBuffer to compare this string to.
- * @return {@code true} if the characters in {@code strbuf} are identical to
- * those in this string. If they are not, {@code false} will be
- * returned.
- * @throws NullPointerException
- * if {@code strbuf} is {@code null}.
- * @since 1.4
- */
- public boolean contentEquals(StringBuffer strbuf) {
- synchronized (strbuf) {
- int size = strbuf.length();
- if (count != size) {
- return false;
- }
- return regionMatches(0, new String(0, size, strbuf.getValue()), 0,
- size);
- }
- }
-
- /**
- * Compares a {@code CharSequence} to this {@code String} to determine if
- * their contents are equal.
- *
- * @param cs
- * the character sequence to compare to.
- * @return {@code true} if equal, otherwise {@code false}
- * @since 1.5
- */
- public boolean contentEquals(CharSequence cs) {
- if (cs == null) {
- throw new NullPointerException("cs == null");
- }
-
- int len = cs.length();
-
- if (len != count) {
- return false;
- }
-
- if (len == 0 && count == 0) {
- return true; // since both are empty strings
- }
-
- return regionMatches(0, cs.toString(), 0, len);
- }
-
- /**
- * Tests whether this string matches the given {@code regularExpression}. This method returns
- * true only if the regular expression matches the <i>entire</i> input string. A common mistake is
- * to assume that this method behaves like {@link #contains}; if you want to match anywhere
- * within the input string, you need to add {@code .*} to the beginning and end of your
- * regular expression. See {@link Pattern#matches}.
- *
- * <p>If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @throws PatternSyntaxException
- * if the syntax of the supplied regular expression is not
- * valid.
- * @throws NullPointerException if {@code regularExpression == null}
- * @since 1.4
- */
- public boolean matches(String regularExpression) {
- return Pattern.matches(regularExpression, this);
- }
-
- /**
- * Replaces all matches for {@code regularExpression} within this string with the given
- * {@code replacement}.
- * See {@link Pattern} for regular expression syntax.
- *
- * <p>If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @throws PatternSyntaxException
- * if the syntax of the supplied regular expression is not
- * valid.
- * @throws NullPointerException if {@code regularExpression == null}
- * @see Pattern
- * @since 1.4
- */
- public String replaceAll(String regularExpression, String replacement) {
- return Pattern.compile(regularExpression).matcher(this).replaceAll(replacement);
- }
-
- /**
- * Replaces the first match for {@code regularExpression} within this string with the given
- * {@code replacement}.
- * See {@link Pattern} for regular expression syntax.
- *
- * <p>If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @throws PatternSyntaxException
- * if the syntax of the supplied regular expression is not
- * valid.
- * @throws NullPointerException if {@code regularExpression == null}
- * @see Pattern
- * @since 1.4
- */
- public String replaceFirst(String regularExpression, String replacement) {
- return Pattern.compile(regularExpression).matcher(this).replaceFirst(replacement);
- }
-
- /**
- * Splits this string using the supplied {@code regularExpression}.
- * Equivalent to {@code split(regularExpression, 0)}.
- * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
- * See {@link Pattern} for regular expression syntax.
- *
- * <p>If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @throws NullPointerException if {@code regularExpression == null}
- * @throws PatternSyntaxException
- * if the syntax of the supplied regular expression is not
- * valid.
- * @see Pattern
- * @since 1.4
- */
- public String[] split(String regularExpression) {
- return split(regularExpression, 0);
- }
-
- /**
- * Splits this string using the supplied {@code regularExpression}.
- * See {@link Pattern#split(CharSequence, int)} for an explanation of {@code limit}.
- * See {@link Pattern} for regular expression syntax.
- *
- * <p>If the same regular expression is to be used for multiple operations, it may be more
- * efficient to reuse a compiled {@code Pattern}.
- *
- * @throws NullPointerException if {@code regularExpression == null}
- * @throws PatternSyntaxException
- * if the syntax of the supplied regular expression is not
- * valid.
- * @since 1.4
- */
- public String[] split(String regularExpression, int limit) {
- String[] result = java.util.regex.Splitter.fastSplit(regularExpression, this, limit);
- return result != null ? result : Pattern.compile(regularExpression).split(this, limit);
- }
-
- /**
- * Has the same result as the substring function, but is present so that
- * string may implement the CharSequence interface.
- *
- * @param start
- * the offset the first character.
- * @param end
- * the offset of one past the last character to include.
- * @return the subsequence requested.
- * @throws IndexOutOfBoundsException
- * if {@code start < 0}, {@code end < 0}, {@code start > end} or
- * {@code end > length()}.
- * @see java.lang.CharSequence#subSequence(int, int)
- * @since 1.4
- */
- public CharSequence subSequence(int start, int end) {
- return substring(start, end);
- }
-
- /**
- * Returns the Unicode code point at the given {@code index}.
- *
- * @throws IndexOutOfBoundsException if {@code index < 0 || index >= length()}
- * @see Character#codePointAt(char[], int, int)
- * @since 1.5
- */
- public int codePointAt(int index) {
- if (index < 0 || index >= count) {
- throw indexAndLength(index);
- }
- return Character.codePointAt(value, offset + index, offset + count);
- }
-
- /**
- * Returns the Unicode code point that precedes the given {@code index}.
- *
- * @throws IndexOutOfBoundsException if {@code index < 1 || index > length()}
- * @see Character#codePointBefore(char[], int, int)
- * @since 1.5
- */
- public int codePointBefore(int index) {
- if (index < 1 || index > count) {
- throw indexAndLength(index);
- }
- return Character.codePointBefore(value, offset + index, offset);
- }
-
- /**
- * Calculates the number of Unicode code points between {@code start}
- * and {@code end}.
- *
- * @param start
- * the inclusive beginning index of the subsequence.
- * @param end
- * the exclusive end index of the subsequence.
- * @return the number of Unicode code points in the subsequence.
- * @throws IndexOutOfBoundsException
- * if {@code start < 0 || end > length() || start > end}
- * @see Character#codePointCount(CharSequence, int, int)
- * @since 1.5
- */
- public int codePointCount(int start, int end) {
- if (start < 0 || end > count || start > end) {
- throw startEndAndLength(start, end);
- }
- return Character.codePointCount(value, offset + start, end - start);
- }
-
- /**
- * Determines if this {@code String} contains the sequence of characters in
- * the {@code CharSequence} passed.
- *
- * @param cs
- * the character sequence to search for.
- * @return {@code true} if the sequence of characters are contained in this
- * string, otherwise {@code false}.
- * @since 1.5
- */
- public boolean contains(CharSequence cs) {
- if (cs == null) {
- throw new NullPointerException("cs == null");
- }
- return indexOf(cs.toString()) >= 0;
- }
-
- /**
- * Returns the index within this object that is offset from {@code index} by
- * {@code codePointOffset} code points.
- *
- * @param index
- * the index within this object to calculate the offset from.
- * @param codePointOffset
- * the number of code points to count.
- * @return the index within this object that is the offset.
- * @throws IndexOutOfBoundsException
- * if {@code index} is negative or greater than {@code length()}
- * or if there aren't enough code points before or after {@code
- * index} to match {@code codePointOffset}.
- * @since 1.5
- */
- public int offsetByCodePoints(int index, int codePointOffset) {
- int s = index + offset;
- int r = Character.offsetByCodePoints(value, offset, count, s, codePointOffset);
- return r - offset;
- }
-
- /**
- * Returns a localized formatted string, using the supplied format and arguments,
- * using the user's default locale.
- *
- * <p>If you're formatting a string other than for human
- * consumption, you should use the {@code format(Locale, String, Object...)}
- * overload and supply {@code Locale.US}. See
- * "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
- *
- * @param format the format string (see {@link java.util.Formatter#format})
- * @param args
- * the list of arguments passed to the formatter. If there are
- * more arguments than required by {@code format},
- * additional arguments are ignored.
- * @return the formatted string.
- * @throws NullPointerException if {@code format == null}
- * @throws java.util.IllegalFormatException
- * if the format is invalid.
- * @since 1.5
- */
- public static String format(String format, Object... args) {
- return format(Locale.getDefault(), format, args);
- }
-
- /**
- * Returns a formatted string, using the supplied format and arguments,
- * localized to the given locale.
- *
- * @param locale
- * the locale to apply; {@code null} value means no localization.
- * @param format the format string (see {@link java.util.Formatter#format})
- * @param args
- * the list of arguments passed to the formatter. If there are
- * more arguments than required by {@code format},
- * additional arguments are ignored.
- * @return the formatted string.
- * @throws NullPointerException if {@code format == null}
- * @throws java.util.IllegalFormatException
- * if the format is invalid.
- * @since 1.5
- */
- public static String format(Locale locale, String format, Object... args) {
- if (format == null) {
- throw new NullPointerException("format == null");
- }
- int bufferSize = format.length() + (args == null ? 0 : args.length * 10);
- Formatter f = new Formatter(new StringBuilder(bufferSize), locale);
- return f.format(format, args).toString();
- }
-
- /*
- * An implementation of a String.indexOf that is supposed to perform
- * substantially better than the default algorithm if the "needle" (the
- * subString being searched for) is a constant string.
- *
- * For example, a JIT, upon encountering a call to String.indexOf(String),
- * where the needle is a constant string, may compute the values cache, md2
- * and lastChar, and change the call to the following method.
- */
- @FindBugsSuppressWarnings("UPM_UNCALLED_PRIVATE_METHOD")
- @SuppressWarnings("unused")
- private static int indexOf(String haystackString, String needleString,
- int cache, int md2, char lastChar) {
- char[] haystack = haystackString.value;
- int haystackOffset = haystackString.offset;
- int haystackLength = haystackString.count;
- char[] needle = needleString.value;
- int needleOffset = needleString.offset;
- int needleLength = needleString.count;
- int needleLengthMinus1 = needleLength - 1;
- int haystackEnd = haystackOffset + haystackLength;
- outer_loop: for (int i = haystackOffset + needleLengthMinus1; i < haystackEnd;) {
- if (lastChar == haystack[i]) {
- for (int j = 0; j < needleLengthMinus1; ++j) {
- if (needle[j + needleOffset] != haystack[i + j
- - needleLengthMinus1]) {
- int skip = 1;
- if ((cache & (1 << haystack[i])) == 0) {
- skip += j;
- }
- i += Math.max(md2, skip);
- continue outer_loop;
- }
- }
- return i - needleLengthMinus1 - haystackOffset;
- }
-
- if ((cache & (1 << haystack[i])) == 0) {
- i += needleLengthMinus1;
- }
- i++;
- }
- return -1;
- }
-}
diff --git a/libdvm/src/main/java/java/lang/Thread.java b/libdvm/src/main/java/java/lang/Thread.java
deleted file mode 100644
index a40dde1..0000000
--- a/libdvm/src/main/java/java/lang/Thread.java
+++ /dev/null
@@ -1,1288 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import dalvik.system.VMStack;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import libcore.util.EmptyArray;
-
-/**
- * A {@code Thread} is a concurrent unit of execution. It has its own call stack
- * for methods being invoked, their arguments and local variables. Each application
- * has at least one thread running when it is started, the main thread, in the main
- * {@link ThreadGroup}. The runtime keeps its own threads in the system thread
- * group.
- *
- * <p>There are two ways to execute code in a new thread.
- * You can either subclass {@code Thread} and overriding its {@link #run()} method,
- * or construct a new {@code Thread} and pass a {@link Runnable} to the constructor.
- * In either case, the {@link #start()} method must be called to actually execute
- * the new {@code Thread}.
- *
- * <p>Each {@code Thread} has an integer priority that affect how the thread is
- * scheduled by the OS. A new thread inherits the priority of its parent.
- * A thread's priority can be set using the {@link #setPriority(int)} method.
- */
-public class Thread implements Runnable {
- private static final int NANOS_PER_MILLI = 1000000;
-
- /** Park states */
- private static class ParkState {
- /** park state indicating unparked */
- private static final int UNPARKED = 1;
-
- /** park state indicating preemptively unparked */
- private static final int PREEMPTIVELY_UNPARKED = 2;
-
- /** park state indicating parked */
- private static final int PARKED = 3;
- }
-
- /**
- * A representation of a thread's state. A given thread may only be in one
- * state at a time.
- */
- public enum State {
- /**
- * The thread has been created, but has never been started.
- */
- NEW,
- /**
- * The thread may be run.
- */
- RUNNABLE,
- /**
- * The thread is blocked and waiting for a lock.
- */
- BLOCKED,
- /**
- * The thread is waiting.
- */
- WAITING,
- /**
- * The thread is waiting for a specified amount of time.
- */
- TIMED_WAITING,
- /**
- * The thread has been terminated.
- */
- TERMINATED
- }
-
- /**
- * The maximum priority value allowed for a thread.
- * This corresponds to (but does not have the same value as)
- * {@code android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY}.
- */
- public static final int MAX_PRIORITY = 10;
-
- /**
- * The minimum priority value allowed for a thread.
- * This corresponds to (but does not have the same value as)
- * {@code android.os.Process.THREAD_PRIORITY_LOWEST}.
- */
- public static final int MIN_PRIORITY = 1;
-
- /**
- * The normal (default) priority value assigned to the main thread.
- * This corresponds to (but does not have the same value as)
- * {@code android.os.Process.THREAD_PRIORITY_DEFAULT}.
-
- */
- public static final int NORM_PRIORITY = 5;
-
- /* some of these are accessed directly by the VM; do not rename them */
- volatile VMThread vmThread;
- volatile ThreadGroup group;
- volatile boolean daemon;
- volatile String name;
- volatile int priority;
- volatile long stackSize;
- Runnable target;
- private static int count = 0;
-
- /**
- * Holds the thread's ID. We simply count upwards, so
- * each Thread has a unique ID.
- */
- private long id;
-
- /**
- * Normal thread local values.
- */
- ThreadLocal.Values localValues;
-
- /**
- * Inheritable thread local values.
- */
- ThreadLocal.Values inheritableValues;
-
- /** Callbacks to run on interruption. */
- private final List<Runnable> interruptActions = new ArrayList<Runnable>();
-
- /**
- * Holds the class loader for this Thread, in case there is one.
- */
- private ClassLoader contextClassLoader;
-
- /**
- * Holds the handler for uncaught exceptions in this Thread,
- * in case there is one.
- */
- private UncaughtExceptionHandler uncaughtHandler;
-
- /**
- * Holds the default handler for uncaught exceptions, in case there is one.
- */
- private static UncaughtExceptionHandler defaultUncaughtHandler;
-
- /**
- * Reflects whether this Thread has already been started. A Thread
- * can only be started once (no recycling). Also, we need it to deduce
- * the proper Thread status.
- */
- boolean hasBeenStarted = false;
-
- /** the park state of the thread */
- private int parkState = ParkState.UNPARKED;
-
- /** The synchronization object responsible for this thread parking. */
- private Object parkBlocker;
-
- /**
- * Constructs a new {@code Thread} with no {@code Runnable} object and a
- * newly generated name. The new {@code Thread} will belong to the same
- * {@code ThreadGroup} as the {@code Thread} calling this constructor.
- *
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread() {
- create(null, null, null, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with a {@code Runnable} object and a
- * newly generated name. The new {@code Thread} will belong to the same
- * {@code ThreadGroup} as the {@code Thread} calling this constructor.
- *
- * @param runnable
- * a {@code Runnable} whose method <code>run</code> will be
- * executed by the new {@code Thread}
- *
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(Runnable runnable) {
- create(null, runnable, null, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with a {@code Runnable} object and name
- * provided. The new {@code Thread} will belong to the same {@code
- * ThreadGroup} as the {@code Thread} calling this constructor.
- *
- * @param runnable
- * a {@code Runnable} whose method <code>run</code> will be
- * executed by the new {@code Thread}
- * @param threadName
- * the name for the {@code Thread} being created
- *
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(Runnable runnable, String threadName) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
-
- create(null, runnable, threadName, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with no {@code Runnable} object and the
- * name provided. The new {@code Thread} will belong to the same {@code
- * ThreadGroup} as the {@code Thread} calling this constructor.
- *
- * @param threadName
- * the name for the {@code Thread} being created
- *
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- *
- */
- public Thread(String threadName) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
-
- create(null, null, threadName, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with a {@code Runnable} object and a
- * newly generated name. The new {@code Thread} will belong to the {@code
- * ThreadGroup} passed as parameter.
- *
- * @param group
- * {@code ThreadGroup} to which the new {@code Thread} will
- * belong
- * @param runnable
- * a {@code Runnable} whose method <code>run</code> will be
- * executed by the new {@code Thread}
- * @throws IllegalThreadStateException
- * if <code>group.destroy()</code> has already been done
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(ThreadGroup group, Runnable runnable) {
- create(group, runnable, null, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with a {@code Runnable} object, the given
- * name and belonging to the {@code ThreadGroup} passed as parameter.
- *
- * @param group
- * ThreadGroup to which the new {@code Thread} will belong
- * @param runnable
- * a {@code Runnable} whose method <code>run</code> will be
- * executed by the new {@code Thread}
- * @param threadName
- * the name for the {@code Thread} being created
- * @throws IllegalThreadStateException
- * if <code>group.destroy()</code> has already been done
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(ThreadGroup group, Runnable runnable, String threadName) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
-
- create(group, runnable, threadName, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with no {@code Runnable} object, the
- * given name and belonging to the {@code ThreadGroup} passed as parameter.
- *
- * @param group
- * {@code ThreadGroup} to which the new {@code Thread} will belong
- * @param threadName
- * the name for the {@code Thread} being created
- * @throws IllegalThreadStateException
- * if <code>group.destroy()</code> has already been done
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(ThreadGroup group, String threadName) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
-
- create(group, null, threadName, 0);
- }
-
- /**
- * Constructs a new {@code Thread} with a {@code Runnable} object, the given
- * name and belonging to the {@code ThreadGroup} passed as parameter.
- *
- * @param group
- * {@code ThreadGroup} to which the new {@code Thread} will
- * belong
- * @param runnable
- * a {@code Runnable} whose method <code>run</code> will be
- * executed by the new {@code Thread}
- * @param threadName
- * the name for the {@code Thread} being created
- * @param stackSize
- * a stack size for the new {@code Thread}. This has a highly
- * platform-dependent interpretation. It may even be ignored
- * completely.
- * @throws IllegalThreadStateException
- * if <code>group.destroy()</code> has already been done
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- public Thread(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
- create(group, runnable, threadName, stackSize);
- }
-
- /**
- * Package-scope method invoked by Dalvik VM to create "internal"
- * threads or attach threads created externally.
- *
- * Don't call Thread.currentThread(), since there may not be such
- * a thing (e.g. for Main).
- */
- Thread(ThreadGroup group, String name, int priority, boolean daemon) {
- synchronized (Thread.class) {
- id = ++Thread.count;
- }
-
- if (name == null) {
- this.name = "Thread-" + id;
- } else {
- this.name = name;
- }
-
- if (group == null) {
- throw new InternalError("group not specified");
- }
-
- this.group = group;
-
- this.target = null;
- this.stackSize = 0;
- this.priority = priority;
- this.daemon = daemon;
-
- /* add ourselves to our ThreadGroup of choice */
- this.group.addThread(this);
- }
-
- /**
- * Initializes a new, existing Thread object with a runnable object,
- * the given name and belonging to the ThreadGroup passed as parameter.
- * This is the method that the several public constructors delegate their
- * work to.
- *
- * @param group ThreadGroup to which the new Thread will belong
- * @param runnable a java.lang.Runnable whose method <code>run</code> will
- * be executed by the new Thread
- * @param threadName Name for the Thread being created
- * @param stackSize Platform dependent stack size
- * @throws IllegalThreadStateException if <code>group.destroy()</code> has
- * already been done
- * @see java.lang.ThreadGroup
- * @see java.lang.Runnable
- */
- private void create(ThreadGroup group, Runnable runnable, String threadName, long stackSize) {
- Thread currentThread = Thread.currentThread();
- if (group == null) {
- group = currentThread.getThreadGroup();
- }
-
- if (group.isDestroyed()) {
- throw new IllegalThreadStateException("Group already destroyed");
- }
-
- this.group = group;
-
- synchronized (Thread.class) {
- id = ++Thread.count;
- }
-
- if (threadName == null) {
- this.name = "Thread-" + id;
- } else {
- this.name = threadName;
- }
-
- this.target = runnable;
- this.stackSize = stackSize;
-
- this.priority = currentThread.getPriority();
-
- this.contextClassLoader = currentThread.contextClassLoader;
-
- // Transfer over InheritableThreadLocals.
- if (currentThread.inheritableValues != null) {
- inheritableValues = new ThreadLocal.Values(currentThread.inheritableValues);
- }
-
- // add ourselves to our ThreadGroup of choice
- this.group.addThread(this);
- }
-
- /**
- * Returns the number of active {@code Thread}s in the running {@code
- * Thread}'s group and its subgroups.
- *
- * @return the number of {@code Thread}s
- */
- public static int activeCount() {
- return currentThread().getThreadGroup().activeCount();
- }
-
- /**
- * Does nothing.
- */
- public final void checkAccess() {
- }
-
- /**
- * Returns the number of stack frames in this thread.
- *
- * @return Number of stack frames
- * @deprecated The results of this call were never well defined. To make
- * things worse, it would depend on whether the Thread was
- * suspended or not, and suspend was deprecated too.
- */
- @Deprecated
- public int countStackFrames() {
- return getStackTrace().length;
- }
-
- /**
- * Returns the Thread of the caller, that is, the current Thread.
- *
- * @return the current Thread.
- */
- public static Thread currentThread() {
- return VMThread.currentThread();
- }
-
- /**
- * Throws {@code UnsupportedOperationException}.
- * @deprecated Not implemented.
- */
- @Deprecated
- public void destroy() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Prints to the standard error stream a text representation of the current
- * stack for this Thread.
- *
- * @see Throwable#printStackTrace()
- */
- public static void dumpStack() {
- new Throwable("stack dump").printStackTrace();
- }
-
- /**
- * Copies an array with all Threads which are in the same ThreadGroup as the
- * receiver - and subgroups - into the array <code>threads</code> passed as
- * parameter. If the array passed as parameter is too small no exception is
- * thrown - the extra elements are simply not copied.
- *
- * @param threads
- * array into which the Threads will be copied
- * @return How many Threads were copied over
- */
- public static int enumerate(Thread[] threads) {
- Thread thread = Thread.currentThread();
- return thread.getThreadGroup().enumerate(threads);
- }
-
- /**
- * Returns a map of all the currently live threads to their stack traces.
- */
- public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
- Map<Thread, StackTraceElement[]> map = new HashMap<Thread, StackTraceElement[]>();
-
- // Find out how many live threads we have. Allocate a bit more
- // space than needed, in case new ones are just being created.
- int count = ThreadGroup.mSystem.activeCount();
- Thread[] threads = new Thread[count + count / 2];
-
- // Enumerate the threads and collect the stacktraces.
- count = ThreadGroup.mSystem.enumerate(threads);
- for (int i = 0; i < count; i++) {
- map.put(threads[i], threads[i].getStackTrace());
- }
-
- return map;
- }
-
- /**
- * Returns the context ClassLoader for this Thread.
- *
- * @return ClassLoader The context ClassLoader
- * @see java.lang.ClassLoader
- * @see #getContextClassLoader()
- */
- public ClassLoader getContextClassLoader() {
- return contextClassLoader;
- }
-
- /**
- * Returns the default exception handler that's executed when uncaught
- * exception terminates a thread.
- *
- * @return an {@link UncaughtExceptionHandler} or <code>null</code> if
- * none exists.
- */
- public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
- return defaultUncaughtHandler;
- }
-
- /**
- * Returns the thread's identifier. The ID is a positive <code>long</code>
- * generated on thread creation, is unique to the thread, and doesn't change
- * during the lifetime of the thread; the ID may be reused after the thread
- * has been terminated.
- *
- * @return the thread's ID.
- */
- public long getId() {
- return id;
- }
-
- /**
- * Returns the name of the Thread.
- */
- public final String getName() {
- return name;
- }
-
- /**
- * Returns the priority of the Thread.
- */
- public final int getPriority() {
- return priority;
- }
-
- /**
- * Returns an array of {@link StackTraceElement} representing the current thread's stack.
- */
- public StackTraceElement[] getStackTrace() {
- StackTraceElement ste[] = VMStack.getThreadStackTrace(this);
- return ste != null ? ste : EmptyArray.STACK_TRACE_ELEMENT;
- }
-
- /**
- * Returns the current state of the Thread. This method is useful for
- * monitoring purposes.
- *
- * @return a {@link State} value.
- */
- public State getState() {
- // TODO This is ugly and should be implemented better.
- VMThread vmt = this.vmThread;
-
- // Make sure we have a valid reference to an object. If native code
- // deletes the reference we won't run into a null reference later.
- VMThread thread = vmThread;
- if (thread != null) {
- // If the Thread Object became invalid or was not yet started,
- // getStatus() will return -1.
- int state = thread.getStatus();
- if(state != -1) {
- return VMThread.STATE_MAP[state];
- }
- }
- return hasBeenStarted ? Thread.State.TERMINATED : Thread.State.NEW;
- }
-
- /**
- * Returns the ThreadGroup to which this Thread belongs.
- *
- * @return the Thread's ThreadGroup
- */
- public final ThreadGroup getThreadGroup() {
- // TODO This should actually be done at native termination.
- if (getState() == Thread.State.TERMINATED) {
- return null;
- } else {
- return group;
- }
- }
-
- /**
- * Returns the thread's uncaught exception handler. If not explicitly set,
- * then the ThreadGroup's handler is returned. If the thread is terminated,
- * then <code>null</code> is returned.
- *
- * @return an {@link UncaughtExceptionHandler} instance or {@code null}.
- */
- public UncaughtExceptionHandler getUncaughtExceptionHandler() {
- if (uncaughtHandler != null)
- return uncaughtHandler;
- else
- return group; // ThreadGroup is instance of UEH
- }
-
- /**
- * Posts an interrupt request to this {@code Thread}. The behavior depends on
- * the state of this {@code Thread}:
- * <ul>
- * <li>
- * {@code Thread}s blocked in one of {@code Object}'s {@code wait()} methods
- * or one of {@code Thread}'s {@code join()} or {@code sleep()} methods will
- * be woken up, their interrupt status will be cleared, and they receive an
- * {@link InterruptedException}.
- * <li>
- * {@code Thread}s blocked in an I/O operation of an
- * {@link java.nio.channels.InterruptibleChannel} will have their interrupt
- * status set and receive an
- * {@link java.nio.channels.ClosedByInterruptException}. Also, the channel
- * will be closed.
- * <li>
- * {@code Thread}s blocked in a {@link java.nio.channels.Selector} will have
- * their interrupt status set and return immediately. They don't receive an
- * exception in this case.
- * <ul>
- *
- * @see Thread#interrupted
- * @see Thread#isInterrupted
- */
- public void interrupt() {
- // Interrupt this thread before running actions so that other
- // threads that observe the interrupt as a result of an action
- // will see that this thread is in the interrupted state.
- VMThread vmt = this.vmThread;
- if (vmt != null) {
- vmt.interrupt();
- }
-
- synchronized (interruptActions) {
- for (int i = interruptActions.size() - 1; i >= 0; i--) {
- interruptActions.get(i).run();
- }
- }
- }
-
- /**
- * Returns a <code>boolean</code> indicating whether the current Thread (
- * <code>currentThread()</code>) has a pending interrupt request (<code>
- * true</code>) or not (<code>false</code>). It also has the side-effect of
- * clearing the flag.
- *
- * @return a <code>boolean</code> indicating the interrupt status
- * @see Thread#currentThread
- * @see Thread#interrupt
- * @see Thread#isInterrupted
- */
- public static boolean interrupted() {
- return VMThread.interrupted();
- }
-
- /**
- * Returns <code>true</code> if the receiver has already been started and
- * still runs code (hasn't died yet). Returns <code>false</code> either if
- * the receiver hasn't been started yet or if it has already started and run
- * to completion and died.
- *
- * @return a <code>boolean</code> indicating the liveness of the Thread
- * @see Thread#start
- */
- public final boolean isAlive() {
- return (vmThread != null);
- }
-
- /**
- * Tests whether this is a daemon thread.
- * A daemon thread only runs as long as there are non-daemon threads running.
- * When the last non-daemon thread ends, the runtime will exit. This is not
- * normally relevant to applications with a UI.
- */
- public final boolean isDaemon() {
- return daemon;
- }
-
- /**
- * Returns a <code>boolean</code> indicating whether the receiver has a
- * pending interrupt request (<code>true</code>) or not (
- * <code>false</code>)
- *
- * @return a <code>boolean</code> indicating the interrupt status
- * @see Thread#interrupt
- * @see Thread#interrupted
- */
- public boolean isInterrupted() {
- VMThread vmt = this.vmThread;
- if (vmt != null) {
- return vmt.isInterrupted();
- }
-
- return false;
- }
-
- /**
- * Blocks the current Thread (<code>Thread.currentThread()</code>) until
- * the receiver finishes its execution and dies.
- *
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception is
- * thrown.
- * @see Object#notifyAll
- * @see java.lang.ThreadDeath
- */
- public final void join() throws InterruptedException {
- VMThread t = vmThread;
- if (t == null) {
- return;
- }
-
- synchronized (t) {
- while (isAlive()) {
- t.wait();
- }
- }
- }
-
- /**
- * Blocks the current Thread (<code>Thread.currentThread()</code>) until
- * the receiver finishes its execution and dies or the specified timeout
- * expires, whatever happens first.
- *
- * <p>A timeout of zero means the calling thread should wait forever unless interrupted.
- *
- * @param millis The maximum time to wait (in milliseconds).
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception is
- * thrown.
- * @see Object#notifyAll
- * @see java.lang.ThreadDeath
- */
- public final void join(long millis) throws InterruptedException {
- join(millis, 0);
- }
-
- /**
- * Blocks the current Thread (<code>Thread.currentThread()</code>) until
- * the receiver finishes its execution and dies or the specified timeout
- * expires, whatever happens first.
- *
- * <p>A timeout of zero means the calling thread should wait forever unless interrupted.
- *
- * @param millis The maximum time to wait (in milliseconds).
- * @param nanos Extra nanosecond precision
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception is
- * thrown.
- * @see Object#notifyAll
- * @see java.lang.ThreadDeath
- */
- public final void join(long millis, int nanos) throws InterruptedException {
- if (millis < 0 || nanos < 0 || nanos >= NANOS_PER_MILLI) {
- throw new IllegalArgumentException("bad timeout: millis=" + millis + ",nanos=" + nanos);
- }
-
- // avoid overflow: if total > 292,277 years, just wait forever
- boolean overflow = millis >= (Long.MAX_VALUE - nanos) / NANOS_PER_MILLI;
- boolean forever = (millis | nanos) == 0;
- if (forever | overflow) {
- join();
- return;
- }
-
- VMThread t = vmThread;
- if (t == null) {
- return;
- }
-
- synchronized (t) {
- if (!isAlive()) {
- return;
- }
-
- // guaranteed not to overflow
- long nanosToWait = millis * NANOS_PER_MILLI + nanos;
-
- // wait until this thread completes or the timeout has elapsed
- long start = System.nanoTime();
- while (true) {
- t.wait(millis, nanos);
- if (!isAlive()) {
- break;
- }
- long nanosElapsed = System.nanoTime() - start;
- long nanosRemaining = nanosToWait - nanosElapsed;
- if (nanosRemaining <= 0) {
- break;
- }
- millis = nanosRemaining / NANOS_PER_MILLI;
- nanos = (int) (nanosRemaining - millis * NANOS_PER_MILLI);
- }
- }
- }
-
- /**
- * Throws {@code UnsupportedOperationException}.
- * @deprecated Only useful in conjunction with deprecated method {@link Thread#suspend}.
- */
- @Deprecated
- public final void resume() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Calls the <code>run()</code> method of the Runnable object the receiver
- * holds. If no Runnable is set, does nothing.
- *
- * @see Thread#start
- */
- public void run() {
- if (target != null) {
- target.run();
- }
- }
-
- /**
- * Set the context ClassLoader for the receiver.
- *
- * @param cl The context ClassLoader
- * @see #getContextClassLoader()
- */
- public void setContextClassLoader(ClassLoader cl) {
- contextClassLoader = cl;
- }
-
- /**
- * Marks this thread as a daemon thread.
- * A daemon thread only runs as long as there are non-daemon threads running.
- * When the last non-daemon thread ends, the runtime will exit. This is not
- * normally relevant to applications with a UI.
- * @throws IllegalThreadStateException - if this thread has already started.
- */
- public final void setDaemon(boolean isDaemon) {
- checkNotStarted();
- if (vmThread == null) {
- daemon = isDaemon;
- }
- }
-
- private void checkNotStarted() {
- if (hasBeenStarted) {
- throw new IllegalThreadStateException("Thread already started");
- }
- }
-
- /**
- * Sets the default uncaught exception handler. This handler is invoked in
- * case any Thread dies due to an unhandled exception.
- *
- * @param handler
- * The handler to set or null.
- */
- public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
- Thread.defaultUncaughtHandler = handler;
- }
-
- /**
- * Adds a runnable to be invoked upon interruption. If this thread has
- * already been interrupted, the runnable will be invoked immediately. The
- * action should be idempotent as it may be invoked multiple times for a
- * single interruption.
- *
- * <p>Each call to this method must be matched with a corresponding call to
- * {@link #popInterruptAction$}.
- *
- * @hide used by NIO
- */
- public final void pushInterruptAction$(Runnable interruptAction) {
- synchronized (interruptActions) {
- interruptActions.add(interruptAction);
- }
-
- if (interruptAction != null && isInterrupted()) {
- interruptAction.run();
- }
- }
-
- /**
- * Removes {@code interruptAction} so it is not invoked upon interruption.
- *
- * @param interruptAction the pushed action, used to check that the call
- * stack is correctly nested.
- *
- * @hide used by NIO
- */
- public final void popInterruptAction$(Runnable interruptAction) {
- synchronized (interruptActions) {
- Runnable removed = interruptActions.remove(interruptActions.size() - 1);
- if (interruptAction != removed) {
- throw new IllegalArgumentException(
- "Expected " + interruptAction + " but was " + removed);
- }
- }
- }
-
- /**
- * Sets the name of the Thread.
- *
- * @param threadName the new name for the Thread
- * @see Thread#getName
- */
- public final void setName(String threadName) {
- if (threadName == null) {
- throw new NullPointerException("threadName == null");
- }
-
- name = threadName;
- VMThread vmt = this.vmThread;
- if (vmt != null) {
- /* notify the VM that the thread name has changed */
- vmt.nameChanged(threadName);
- }
- }
-
- /**
- * Sets the priority of this thread. If the requested priority is greater than the
- * parent thread group's {@link java.lang.ThreadGroup#getMaxPriority}, the group's maximum
- * priority will be used instead.
- *
- * @throws IllegalArgumentException - if the new priority is greater than {@link #MAX_PRIORITY}
- * or less than {@link #MIN_PRIORITY}
- */
- public final void setPriority(int priority) {
- if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
- throw new IllegalArgumentException("Priority out of range: " + priority);
- }
-
- if (priority > group.getMaxPriority()) {
- priority = group.getMaxPriority();
- }
-
- this.priority = priority;
-
- VMThread vmt = this.vmThread;
- if (vmt != null) {
- vmt.setPriority(priority);
- }
- }
-
- /**
- * <p>
- * Sets the uncaught exception handler. This handler is invoked in case this
- * Thread dies due to an unhandled exception.
- * </p>
- *
- * @param handler
- * The handler to set or <code>null</code>.
- */
- public void setUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
- uncaughtHandler = handler;
- }
-
- /**
- * Causes the thread which sent this message to sleep for the given interval
- * of time (given in milliseconds). The precision is not guaranteed - the
- * Thread may sleep more or less than requested.
- *
- * @param time
- * The time to sleep in milliseconds.
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception
- * is thrown.
- * @see Thread#interrupt()
- */
- public static void sleep(long time) throws InterruptedException {
- Thread.sleep(time, 0);
- }
-
- /**
- * Causes the thread which sent this message to sleep for the given interval
- * of time (given in milliseconds and nanoseconds). The precision is not
- * guaranteed - the Thread may sleep more or less than requested.
- *
- * @param millis
- * The time to sleep in milliseconds.
- * @param nanos
- * Extra nanosecond precision
- * @throws InterruptedException if the current thread has been interrupted.
- * The interrupted status of the current thread will be cleared before the exception
- * is thrown.
- * @see Thread#interrupt()
- */
- public static void sleep(long millis, int nanos) throws InterruptedException {
- VMThread.sleep(millis, nanos);
- }
-
- /**
- * Starts the new Thread of execution. The <code>run()</code> method of
- * the receiver will be called by the receiver Thread itself (and not the
- * Thread calling <code>start()</code>).
- *
- * @throws IllegalThreadStateException - if this thread has already started.
- * @see Thread#run
- */
- public synchronized void start() {
- checkNotStarted();
-
- hasBeenStarted = true;
-
- VMThread.create(this, stackSize);
- }
-
- /**
- * Requests the receiver Thread to stop and throw ThreadDeath. The Thread is
- * resumed if it was suspended and awakened if it was sleeping, so that it
- * can proceed to throw ThreadDeath.
- *
- * @deprecated Stopping a thread in this manner is unsafe and can
- * leave your application and the VM in an unpredictable state.
- */
- @Deprecated
- public final void stop() {
- stop(new ThreadDeath());
- }
-
- /**
- * Throws {@code UnsupportedOperationException}.
- * @deprecated Stopping a thread in this manner is unsafe and can
- * leave your application and the VM in an unpredictable state.
- */
- @Deprecated
- public final synchronized void stop(Throwable throwable) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Throws {@code UnsupportedOperationException}.
- * @deprecated May cause deadlocks.
- */
- @Deprecated
- public final void suspend() {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns a string containing a concise, human-readable description of the
- * Thread. It includes the Thread's name, priority, and group name.
- *
- * @return a printable representation for the receiver.
- */
- @Override
- public String toString() {
- return "Thread[" + name + "," + priority + "," + group.getName() + "]";
- }
-
- /**
- * Causes the calling Thread to yield execution time to another Thread that
- * is ready to run. The actual scheduling is implementation-dependent.
- */
- public static void yield() {
- VMThread.yield();
- }
-
- /**
- * Indicates whether the current Thread has a monitor lock on the specified
- * object.
- *
- * @param object the object to test for the monitor lock
- * @return true if the current thread has a monitor lock on the specified
- * object; false otherwise
- */
- public static boolean holdsLock(Object object) {
- return currentThread().vmThread.holdsLock(object);
- }
-
- /**
- * Implemented by objects that want to handle cases where a thread is being
- * terminated by an uncaught exception. Upon such termination, the handler
- * is notified of the terminating thread and causal exception. If there is
- * no explicit handler set then the thread's group is the default handler.
- */
- public static interface UncaughtExceptionHandler {
- /**
- * The thread is being terminated by an uncaught exception. Further
- * exceptions thrown in this method are prevent the remainder of the
- * method from executing, but are otherwise ignored.
- *
- * @param thread the thread that has an uncaught exception
- * @param ex the exception that was thrown
- */
- void uncaughtException(Thread thread, Throwable ex);
- }
-
- /**
- * Unparks this thread. This unblocks the thread it if it was
- * previously parked, or indicates that the thread is "preemptively
- * unparked" if it wasn't already parked. The latter means that the
- * next time the thread is told to park, it will merely clear its
- * latent park bit and carry on without blocking.
- *
- * <p>See {@link java.util.concurrent.locks.LockSupport} for more
- * in-depth information of the behavior of this method.</p>
- *
- * @hide for Unsafe
- */
- public void unpark() {
- VMThread vmt = vmThread;
-
- if (vmt == null) {
- /*
- * vmThread is null before the thread is start()ed. In
- * this case, we just go ahead and set the state to
- * PREEMPTIVELY_UNPARKED. Since this happens before the
- * thread is started, we don't have to worry about
- * synchronizing with it.
- */
- parkState = ParkState.PREEMPTIVELY_UNPARKED;
- return;
- }
-
- synchronized (vmt) {
- switch (parkState) {
- case ParkState.PREEMPTIVELY_UNPARKED: {
- /*
- * Nothing to do in this case: By definition, a
- * preemptively unparked thread is to remain in
- * the preemptively unparked state if it is told
- * to unpark.
- */
- break;
- }
- case ParkState.UNPARKED: {
- parkState = ParkState.PREEMPTIVELY_UNPARKED;
- break;
- }
- default /*parked*/: {
- parkState = ParkState.UNPARKED;
- vmt.notifyAll();
- break;
- }
- }
- }
- }
-
- /**
- * Parks the current thread for a particular number of nanoseconds, or
- * indefinitely. If not indefinitely, this method unparks the thread
- * after the given number of nanoseconds if no other thread unparks it
- * first. If the thread has been "preemptively unparked," this method
- * cancels that unparking and returns immediately. This method may
- * also return spuriously (that is, without the thread being told to
- * unpark and without the indicated amount of time elapsing).
- *
- * <p>See {@link java.util.concurrent.locks.LockSupport} for more
- * in-depth information of the behavior of this method.</p>
- *
- * <p>This method must only be called when <code>this</code> is the current
- * thread.
- *
- * @param nanos number of nanoseconds to park for or <code>0</code>
- * to park indefinitely
- * @throws IllegalArgumentException thrown if <code>nanos < 0</code>
- *
- * @hide for Unsafe
- */
- public void parkFor(long nanos) {
- VMThread vmt = vmThread;
-
- if (vmt == null) {
- // Running threads should always have an associated vmThread.
- throw new AssertionError();
- }
-
- synchronized (vmt) {
- switch (parkState) {
- case ParkState.PREEMPTIVELY_UNPARKED: {
- parkState = ParkState.UNPARKED;
- break;
- }
- case ParkState.UNPARKED: {
- long millis = nanos / NANOS_PER_MILLI;
- nanos %= NANOS_PER_MILLI;
-
- parkState = ParkState.PARKED;
- try {
- vmt.wait(millis, (int) nanos);
- } catch (InterruptedException ex) {
- interrupt();
- } finally {
- /*
- * Note: If parkState manages to become
- * PREEMPTIVELY_UNPARKED before hitting this
- * code, it should left in that state.
- */
- if (parkState == ParkState.PARKED) {
- parkState = ParkState.UNPARKED;
- }
- }
- break;
- }
- default /*parked*/: {
- throw new AssertionError(
- "shouldn't happen: attempt to repark");
- }
- }
- }
- }
-
- /**
- * Parks the current thread until the specified system time. This
- * method attempts to unpark the current thread immediately after
- * <code>System.currentTimeMillis()</code> reaches the specified
- * value, if no other thread unparks it first. If the thread has
- * been "preemptively unparked," this method cancels that
- * unparking and returns immediately. This method may also return
- * spuriously (that is, without the thread being told to unpark
- * and without the indicated amount of time elapsing).
- *
- * <p>See {@link java.util.concurrent.locks.LockSupport} for more
- * in-depth information of the behavior of this method.</p>
- *
- * <p>This method must only be called when <code>this</code> is the
- * current thread.
- *
- * @param time the time after which the thread should be unparked,
- * in absolute milliseconds-since-the-epoch
- *
- * @hide for Unsafe
- */
- public void parkUntil(long time) {
- VMThread vmt = vmThread;
-
- if (vmt == null) {
- // Running threads should always have an associated vmThread.
- throw new AssertionError();
- }
-
- synchronized (vmt) {
- /*
- * Note: This conflates the two time bases of "wall clock"
- * time and "monotonic uptime" time. However, given that
- * the underlying system can only wait on monotonic time,
- * it is unclear if there is any way to avoid the
- * conflation. The downside here is that if, having
- * calculated the delay, the wall clock gets moved ahead,
- * this method may not return until well after the wall
- * clock has reached the originally designated time. The
- * reverse problem (the wall clock being turned back)
- * isn't a big deal, since this method is allowed to
- * spuriously return for any reason, and this situation
- * can safely be construed as just such a spurious return.
- */
- long delayMillis = time - System.currentTimeMillis();
-
- if (delayMillis <= 0) {
- parkState = ParkState.UNPARKED;
- } else {
- parkFor(delayMillis * NANOS_PER_MILLI);
- }
- }
- }
-}
diff --git a/libdvm/src/main/java/java/lang/ThreadGroup.java b/libdvm/src/main/java/java/lang/ThreadGroup.java
deleted file mode 100644
index 7fc6b72..0000000
--- a/libdvm/src/main/java/java/lang/ThreadGroup.java
+++ /dev/null
@@ -1,726 +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.lang;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import libcore.util.CollectionUtils;
-
-/**
- * {@code ThreadGroup} is a means of organizing threads into a hierarchical structure.
- * This class is obsolete. See <i>Effective Java</i> Item 73, "Avoid thread groups" for details.
- * @see Thread
- */
-public class ThreadGroup implements Thread.UncaughtExceptionHandler {
-
- // Name of this ThreadGroup
- // VM needs this field name for debugging.
- private String name;
-
- // Maximum priority for Threads inside this ThreadGroup
- private int maxPriority = Thread.MAX_PRIORITY;
-
- // The ThreadGroup to which this ThreadGroup belongs
- // VM needs this field name for debugging.
- final ThreadGroup parent;
-
- /**
- * Weak references to the threads in this group.
- * Access is guarded by synchronizing on this field.
- */
- private final List<WeakReference<Thread>> threadRefs = new ArrayList<WeakReference<Thread>>(5);
-
- /**
- * View of the threads.
- * Access is guarded by synchronizing on threadRefs.
- */
- private final Iterable<Thread> threads = CollectionUtils.dereferenceIterable(threadRefs, true);
-
- /**
- * Thread groups. Access is guarded by synchronizing on this field.
- */
- private final List<ThreadGroup> groups = new ArrayList<ThreadGroup>(3);
-
- // Whether this ThreadGroup is a daemon ThreadGroup or not
- private boolean isDaemon;
-
- // Whether this ThreadGroup has already been destroyed or not
- private boolean isDestroyed;
-
- /* the VM uses these directly; do not rename */
- static final ThreadGroup mSystem = new ThreadGroup();
- static final ThreadGroup mMain = new ThreadGroup(mSystem, "main");
-
- /**
- * Constructs a new {@code ThreadGroup} with the given name. The new {@code ThreadGroup}
- * will be child of the {@code ThreadGroup} to which the calling thread belongs.
- *
- * @param name the name
- * @see Thread#currentThread
- */
- public ThreadGroup(String name) {
- this(Thread.currentThread().getThreadGroup(), name);
- }
-
- /**
- * Constructs a new {@code ThreadGroup} with the given name, as a child of the
- * given {@code ThreadGroup}.
- *
- * @param parent the parent
- * @param name the name
- * @throws NullPointerException if {@code parent == null}
- * @throws IllegalThreadStateException if {@code parent} has been
- * destroyed already
- */
- public ThreadGroup(ThreadGroup parent, String name) {
- if (parent == null) {
- throw new NullPointerException("parent == null");
- }
- this.name = name;
- this.parent = parent;
- if (parent != null) {
- parent.add(this);
- this.setMaxPriority(parent.getMaxPriority());
- if (parent.isDaemon()) {
- this.setDaemon(true);
- }
- }
- }
-
- /**
- * Initialize the special "system" ThreadGroup. Was "main" in Harmony,
- * but we have an additional group above that in Android.
- */
- private ThreadGroup() {
- this.name = "system";
- this.parent = null;
- }
-
- /**
- * Returns the number of running {@code Thread}s which are children of this thread group,
- * directly or indirectly.
- *
- * @return the number of children
- */
- public int activeCount() {
- int count = 0;
- synchronized (threadRefs) {
- for (Thread thread : threads) {
- if (thread.isAlive()) {
- count++;
- }
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- count += group.activeCount();
- }
- }
- return count;
- }
-
- /**
- * Returns the number of {@code ThreadGroup}s which are children of this group,
- * directly or indirectly.
- *
- * @return the number of children
- */
- public int activeGroupCount() {
- int count = 0;
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- // One for this group & the subgroups
- count += 1 + group.activeGroupCount();
- }
- }
- return count;
- }
-
- /**
- * Adds a {@code ThreadGroup} to this thread group.
- *
- * @param g ThreadGroup to add
- * @throws IllegalThreadStateException if this group has been destroyed already
- */
- private void add(ThreadGroup g) throws IllegalThreadStateException {
- synchronized (groups) {
- if (isDestroyed) {
- throw new IllegalThreadStateException();
- }
- groups.add(g);
- }
- }
-
- /**
- * Does nothing. The definition of this method depends on the deprecated
- * method {@link #suspend()}. The exact behavior of this call was never
- * specified.
- *
- * @param b Used to control low memory implicit suspension
- * @return {@code true} (always)
- *
- * @deprecated Required deprecated method {@link #suspend()}.
- */
- @Deprecated
- public boolean allowThreadSuspension(boolean b) {
- // Does not apply to this VM, no-op
- return true;
- }
-
- /**
- * Does nothing.
- */
- public final void checkAccess() {
- }
-
- /**
- * Destroys this thread group and recursively all its subgroups. It is only legal
- * to destroy a {@code ThreadGroup} that has no threads in it. Any daemon
- * {@code ThreadGroup} is destroyed automatically when it becomes empty (no threads
- * or thread groups in it).
- *
- * @throws IllegalThreadStateException if this thread group or any of its
- * subgroups has been destroyed already or if it still contains
- * threads.
- */
- public final void destroy() {
- synchronized (threadRefs) {
- synchronized (groups) {
- if (isDestroyed) {
- throw new IllegalThreadStateException(
- "Thread group was already destroyed: "
- + (this.name != null ? this.name : "n/a"));
- }
- if (threads.iterator().hasNext()) {
- throw new IllegalThreadStateException(
- "Thread group still contains threads: "
- + (this.name != null ? this.name : "n/a"));
- }
- // Call recursively for subgroups
- while (!groups.isEmpty()) {
- // We always get the first element - remember, when the
- // child dies it removes itself from our collection. See
- // below.
- groups.get(0).destroy();
- }
-
- if (parent != null) {
- parent.remove(this);
- }
-
- // Now that the ThreadGroup is really destroyed it can be tagged as so
- this.isDestroyed = true;
- }
- }
- }
-
- /*
- * Auxiliary method that destroys this thread group and recursively all its
- * subgroups if this is a daemon ThreadGroup.
- *
- * @see #destroy
- * @see #setDaemon
- * @see #isDaemon
- */
- private void destroyIfEmptyDaemon() {
- // Has to be non-destroyed daemon to make sense
- synchronized (threadRefs) {
- if (isDaemon && !isDestroyed && !threads.iterator().hasNext()) {
- synchronized (groups) {
- if (groups.isEmpty()) {
- destroy();
- }
- }
- }
- }
- }
-
- /**
- * Iterates over all active threads in this group (and its sub-groups) and
- * stores the threads in the given array. Returns when the array is full or
- * no more threads remain, whichever happens first.
- *
- * <p>Note that this method will silently ignore any threads that don't fit in the
- * supplied array.
- *
- * @param threads the array into which the {@code Thread}s will be copied
- * @return the number of {@code Thread}s that were copied
- */
- public int enumerate(Thread[] threads) {
- return enumerate(threads, true);
- }
-
- /**
- * Iterates over all active threads in this group (and, optionally, its
- * sub-groups) and stores the threads in the given array. Returns when the
- * array is full or no more threads remain, whichever happens first.
- *
- * <p>Note that this method will silently ignore any threads that don't fit in the
- * supplied array.
- *
- * @param threads the array into which the {@code Thread}s will be copied
- * @param recurse indicates whether {@code Thread}s in subgroups should be
- * recursively copied as well
- * @return the number of {@code Thread}s that were copied
- */
- public int enumerate(Thread[] threads, boolean recurse) {
- return enumerateGeneric(threads, recurse, 0, true);
- }
-
- /**
- * Iterates over all thread groups in this group (and its sub-groups) and
- * and stores the groups in the given array. Returns when the array is full
- * or no more groups remain, whichever happens first.
- *
- * <p>Note that this method will silently ignore any thread groups that don't fit in the
- * supplied array.
- *
- * @param groups the array into which the {@code ThreadGroup}s will be copied
- * @return the number of {@code ThreadGroup}s that were copied
- */
- public int enumerate(ThreadGroup[] groups) {
- return enumerate(groups, true);
- }
-
- /**
- * Iterates over all thread groups in this group (and, optionally, its
- * sub-groups) and stores the groups in the given array. Returns when
- * the array is full or no more groups remain, whichever happens first.
- *
- * <p>Note that this method will silently ignore any thread groups that don't fit in the
- * supplied array.
- *
- * @param groups the array into which the {@code ThreadGroup}s will be copied
- * @param recurse indicates whether {@code ThreadGroup}s in subgroups should be
- * recursively copied as well or not
- * @return the number of {@code ThreadGroup}s that were copied
- */
- public int enumerate(ThreadGroup[] groups, boolean recurse) {
- return enumerateGeneric(groups, recurse, 0, false);
- }
-
- /**
- * Copies into <param>enumeration</param> starting at
- * <param>enumerationIndex</param> all Threads or ThreadGroups in the
- * receiver. If <param>recurse</param> is true, recursively enumerate the
- * elements in subgroups.
- *
- * If the array passed as parameter is too small no exception is thrown -
- * the extra elements are simply not copied.
- *
- * @param enumeration array into which the elements will be copied
- * @param recurse Indicates whether subgroups should be enumerated or not
- * @param enumerationIndex Indicates in which position of the enumeration
- * array we are
- * @param enumeratingThreads Indicates whether we are enumerating Threads or
- * ThreadGroups
- * @return How many elements were enumerated/copied over
- */
- private int enumerateGeneric(Object[] enumeration, boolean recurse, int enumerationIndex,
- boolean enumeratingThreads) {
- if (enumeratingThreads) {
- synchronized (threadRefs) {
- // walk the references directly so we can iterate in reverse order
- for (int i = threadRefs.size() - 1; i >= 0; --i) {
- Thread thread = threadRefs.get(i).get();
- if (thread != null && thread.isAlive()) {
- if (enumerationIndex >= enumeration.length) {
- return enumerationIndex;
- }
- enumeration[enumerationIndex++] = thread;
- }
- }
- }
- } else {
- synchronized (groups) {
- for (int i = groups.size() - 1; i >= 0; --i) {
- if (enumerationIndex >= enumeration.length) {
- return enumerationIndex;
- }
- enumeration[enumerationIndex++] = groups.get(i);
- }
- }
- }
-
- if (recurse) {
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- if (enumerationIndex >= enumeration.length) {
- return enumerationIndex;
- }
- enumerationIndex = group.enumerateGeneric(enumeration, recurse,
- enumerationIndex, enumeratingThreads);
- }
- }
- }
- return enumerationIndex;
- }
-
- /**
- * Returns the maximum allowed priority for a {@code Thread} in this thread group.
- *
- * @return the maximum priority
- *
- * @see #setMaxPriority
- */
- public final int getMaxPriority() {
- return maxPriority;
- }
-
- /**
- * Returns the name of this thread group.
- *
- * @return the group's name
- */
- public final String getName() {
- return name;
- }
-
- /**
- * Returns this thread group's parent {@code ThreadGroup}. It can be null if this
- * is the the root ThreadGroup.
- *
- * @return the parent
- */
- public final ThreadGroup getParent() {
- return parent;
- }
-
- /**
- * Interrupts every {@code Thread} in this group and recursively in all its
- * subgroups.
- *
- * @see Thread#interrupt
- */
- public final void interrupt() {
- synchronized (threadRefs) {
- for (Thread thread : threads) {
- thread.interrupt();
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- group.interrupt();
- }
- }
- }
-
- /**
- * Checks whether this thread group is a daemon {@code ThreadGroup}.
- *
- * @return true if this thread group is a daemon {@code ThreadGroup}
- *
- * @see #setDaemon
- * @see #destroy
- */
- public final boolean isDaemon() {
- return isDaemon;
- }
-
- /**
- * Checks whether this thread group has already been destroyed.
- *
- * @return true if this thread group has already been destroyed
- * @see #destroy
- */
- public synchronized boolean isDestroyed() {
- return isDestroyed;
- }
-
- /**
- * Outputs to {@code System.out} a text representation of the
- * hierarchy of {@code Thread}s and {@code ThreadGroup}s in this thread group (and recursively).
- * Proper indentation is used to show the nesting of groups inside groups
- * and threads inside groups.
- */
- public void list() {
- // We start in a fresh line
- System.out.println();
- list(0);
- }
-
- /*
- * Outputs to {@code System.out}a text representation of the
- * hierarchy of Threads and ThreadGroups in this thread group (and recursively).
- * The indentation will be four spaces per level of nesting.
- *
- * @param levels How many levels of nesting, so that proper indentation can
- * be output.
- */
- private void list(int levels) {
- indent(levels);
- System.out.println(this.toString());
-
- ++levels;
- synchronized (threadRefs) {
- for (Thread thread : threads) {
- indent(levels);
- System.out.println(thread);
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- group.list(levels);
- }
- }
- }
-
- private void indent(int levels) {
- for (int i = 0; i < levels; i++) {
- System.out.print(" "); // 4 spaces for each level
- }
- }
-
- /**
- * Checks whether this thread group is a direct or indirect parent group of a
- * given {@code ThreadGroup}.
- *
- * @param g the potential child {@code ThreadGroup}
- * @return true if this thread group is parent of {@code g}
- */
- public final boolean parentOf(ThreadGroup g) {
- while (g != null) {
- if (this == g) {
- return true;
- }
- g = g.parent;
- }
- return false;
- }
-
- /**
- * Removes an immediate subgroup.
- *
- * @param g ThreadGroup to remove
- *
- * @see #add(Thread)
- * @see #add(ThreadGroup)
- */
- private void remove(ThreadGroup g) {
- synchronized (groups) {
- for (Iterator<ThreadGroup> i = groups.iterator(); i.hasNext(); ) {
- ThreadGroup threadGroup = i.next();
- if (threadGroup.equals(g)) {
- i.remove();
- break;
- }
- }
- }
- destroyIfEmptyDaemon();
- }
-
- /**
- * Resumes every thread in this group and recursively in all its
- * subgroups.
- *
- * @see Thread#resume
- * @see #suspend
- *
- * @deprecated Requires deprecated method {@link Thread#resume()}.
- */
- @SuppressWarnings("deprecation")
- @Deprecated
- public final void resume() {
- synchronized (threadRefs) {
- for (Thread thread : threads) {
- thread.resume();
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- group.resume();
- }
- }
- }
-
- /**
- * Sets whether this is a daemon {@code ThreadGroup} or not. Daemon
- * thread groups are automatically destroyed when they become empty.
- *
- * @param isDaemon the new value
- * @see #isDaemon
- * @see #destroy
- */
- public final void setDaemon(boolean isDaemon) {
- this.isDaemon = isDaemon;
- }
-
- /**
- * Configures the maximum allowed priority for a {@code Thread} in this group and
- * recursively in all its subgroups.
- *
- * <p>A caller can never increase the maximum priority of a thread group.
- * Such an attempt will not result in an exception, it will
- * simply leave the thread group with its current maximum priority.
- *
- * @param newMax the new maximum priority to be set
- *
- * @throws IllegalArgumentException if the new priority is greater than
- * Thread.MAX_PRIORITY or less than Thread.MIN_PRIORITY
- *
- * @see #getMaxPriority
- */
- public final void setMaxPriority(int newMax) {
- if (newMax <= this.maxPriority) {
- if (newMax < Thread.MIN_PRIORITY) {
- newMax = Thread.MIN_PRIORITY;
- }
-
- int parentPriority = parent == null ? newMax : parent.getMaxPriority();
- this.maxPriority = parentPriority <= newMax ? parentPriority : newMax;
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- group.setMaxPriority(newMax);
- }
- }
- }
- }
-
- /**
- * Stops every thread in this group and recursively in all its subgroups.
- *
- * @see Thread#stop()
- * @see Thread#stop(Throwable)
- * @see ThreadDeath
- *
- * @deprecated Requires deprecated method {@link Thread#stop()}.
- */
- @SuppressWarnings("deprecation")
- @Deprecated
- public final void stop() {
- if (stopHelper()) {
- Thread.currentThread().stop();
- }
- }
-
- @SuppressWarnings("deprecation")
- private boolean stopHelper() {
- boolean stopCurrent = false;
- synchronized (threadRefs) {
- Thread current = Thread.currentThread();
- for (Thread thread : threads) {
- if (thread == current) {
- stopCurrent = true;
- } else {
- thread.stop();
- }
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- stopCurrent |= group.stopHelper();
- }
- }
- return stopCurrent;
- }
-
- /**
- * Suspends every thread in this group and recursively in all its
- * subgroups.
- *
- * @see Thread#suspend
- * @see #resume
- *
- * @deprecated Requires deprecated method {@link Thread#suspend()}.
- */
- @SuppressWarnings("deprecation")
- @Deprecated
- public final void suspend() {
- if (suspendHelper()) {
- Thread.currentThread().suspend();
- }
- }
-
- @SuppressWarnings("deprecation")
- private boolean suspendHelper() {
- boolean suspendCurrent = false;
- synchronized (threadRefs) {
- Thread current = Thread.currentThread();
- for (Thread thread : threads) {
- if (thread == current) {
- suspendCurrent = true;
- } else {
- thread.suspend();
- }
- }
- }
- synchronized (groups) {
- for (ThreadGroup group : groups) {
- suspendCurrent |= group.suspendHelper();
- }
- }
- return suspendCurrent;
- }
-
- @Override
- public String toString() {
- return getClass().getName() + "[name=" + getName()
- + ",maxPriority=" + getMaxPriority() + "]";
- }
-
- /**
- * Handles uncaught exceptions. Any uncaught exception in any {@code Thread}
- * is forwarded to the thread's {@code ThreadGroup} by invoking this
- * method.
- *
- * <p>New code should use {@link Thread#setUncaughtExceptionHandler} instead of thread groups.
- *
- * @param t the Thread that terminated with an uncaught exception
- * @param e the uncaught exception itself
- */
- public void uncaughtException(Thread t, Throwable e) {
- if (parent != null) {
- parent.uncaughtException(t, e);
- } else if (Thread.getDefaultUncaughtExceptionHandler() != null) {
- // TODO The spec is unclear regarding this. What do we do?
- Thread.getDefaultUncaughtExceptionHandler().uncaughtException(t, e);
- } else if (!(e instanceof ThreadDeath)) {
- // No parent group, has to be 'system' Thread Group
- e.printStackTrace(System.err);
- }
- }
-
- /**
- * Called by the Thread constructor.
- */
- final void addThread(Thread thread) throws IllegalThreadStateException {
- synchronized (threadRefs) {
- if (isDestroyed) {
- throw new IllegalThreadStateException();
- }
- threadRefs.add(new WeakReference<Thread>(thread));
- }
- }
-
- /**
- * Called by the VM when a Thread dies.
- */
- final void removeThread(Thread thread) throws IllegalThreadStateException {
- synchronized (threadRefs) {
- for (Iterator<Thread> i = threads.iterator(); i.hasNext(); ) {
- if (i.next().equals(thread)) {
- i.remove();
- break;
- }
- }
- }
- destroyIfEmptyDaemon();
- }
-}
diff --git a/libdvm/src/main/java/java/lang/VMClassLoader.java b/libdvm/src/main/java/java/lang/VMClassLoader.java
deleted file mode 100644
index d7162c6..0000000
--- a/libdvm/src/main/java/java/lang/VMClassLoader.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-class VMClassLoader {
-
- /**
- * Get a resource from a file in the bootstrap class path.
- *
- * It would be simpler to just walk through the class path elements
- * ourselves, but that would require reopening Jar files.
- *
- * We assume that the bootclasspath can't change once the VM has
- * started. This assumption seems to be supported by the spec.
- */
- static URL getResource(String name) {
- int numEntries = getBootClassPathSize();
- for (int i = 0; i < numEntries; i++) {
- String urlStr = getBootClassPathResource(name, i);
- if (urlStr != null) {
- try {
- return new URL(urlStr);
- } catch (MalformedURLException mue) {
- mue.printStackTrace();
- // unexpected; keep going
- }
- }
- }
- return null;
- }
-
- /*
- * Get an enumeration with all matching resources.
- */
- static List<URL> getResources(String name) {
- ArrayList<URL> list = new ArrayList<URL>();
- int numEntries = getBootClassPathSize();
- for (int i = 0; i < numEntries; i++) {
- String urlStr = getBootClassPathResource(name, i);
- if (urlStr != null) {
- try {
- list.add(new URL(urlStr));
- } catch (MalformedURLException mue) {
- mue.printStackTrace();
- // unexpected; keep going
- }
- }
- }
- return list;
- }
-
- /**
- * Load class with bootstrap class loader.
- */
- native static Class loadClass(String name, boolean resolve) throws ClassNotFoundException;
-
- native static Class getPrimitiveClass(char type);
-
- native static Class findLoadedClass(ClassLoader cl, String name);
-
- /**
- * Boot class path manipulation, for getResources().
- */
- native private static int getBootClassPathSize();
- native private static String getBootClassPathResource(String name, int index);
-}
diff --git a/libdvm/src/main/java/java/lang/VMThread.java b/libdvm/src/main/java/java/lang/VMThread.java
deleted file mode 100644
index 01f6ee3..0000000
--- a/libdvm/src/main/java/java/lang/VMThread.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang;
-
-class VMThread {
- Thread thread;
- int vmData;
-
- VMThread(Thread t) {
- thread = t;
- }
-
- native static void create(Thread t, long stackSize);
-
- static native Thread currentThread();
- static native boolean interrupted();
- static native void sleep (long msec, int nsec) throws InterruptedException;
- static native void yield();
-
- native void interrupt();
-
- native boolean isInterrupted();
-
- /**
- * Starts the VMThread (and thus the Java Thread) with the given
- * stack size.
- */
- void start(long stackSize) {
- VMThread.create(thread, stackSize);
- }
-
- /**
- * Queries whether this Thread holds a monitor lock on the
- * given object.
- */
- native boolean holdsLock(Object object);
-
- native void setPriority(int newPriority);
- native int getStatus();
-
- /**
- * Holds a mapping from native Thread statuses to Java one. Required for
- * translating back the result of getStatus().
- */
- static final Thread.State[] STATE_MAP = new Thread.State[] {
- Thread.State.TERMINATED, // ZOMBIE
- Thread.State.RUNNABLE, // RUNNING
- Thread.State.TIMED_WAITING, // TIMED_WAIT
- Thread.State.BLOCKED, // MONITOR
- Thread.State.WAITING, // WAIT
- Thread.State.NEW, // INITIALIZING
- Thread.State.NEW, // STARTING
- Thread.State.RUNNABLE, // NATIVE
- Thread.State.WAITING, // VMWAIT
- Thread.State.RUNNABLE // SUSPENDED
- };
-
- /**
- * Tell the VM that the thread's name has changed. This is useful for
- * DDMS, which would otherwise be oblivious to Thread.setName calls.
- */
- native void nameChanged(String newName);
-}
diff --git a/libdvm/src/main/java/java/lang/ref/Reference.java b/libdvm/src/main/java/java/lang/ref/Reference.java
deleted file mode 100644
index bd63535..0000000
--- a/libdvm/src/main/java/java/lang/ref/Reference.java
+++ /dev/null
@@ -1,200 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.ref;
-
-/**
- * Provides an abstract class which describes behavior common to all reference
- * objects. It is not possible to create immediate subclasses of
- * {@code Reference} in addition to the ones provided by this package. It is
- * also not desirable to do so, since references require very close cooperation
- * with the system's garbage collector. The existing, specialized reference
- * classes should be used instead.
- *
- * <p>Three different type of references exist, each being weaker than the preceding one:
- * {@link java.lang.ref.SoftReference}, {@link java.lang.ref.WeakReference}, and
- * {@link java.lang.ref.PhantomReference}. "Weakness" here means that less restrictions are
- * being imposed on the garbage collector as to when it is allowed to
- * actually garbage-collect the referenced object.
- *
- * <p>In order to use reference objects properly it is important to understand
- * the different types of reachability that trigger their clearing and
- * enqueueing. The following table lists these, from strongest to weakest.
- * For each row, an object is said to have the reachability on the left side
- * if (and only if) it fulfills all of the requirements on the right side. In
- * all rows, consider the <em>root set</em> to be a set of references that
- * are "resistant" to garbage collection (that is, running threads, method
- * parameters, local variables, static fields and the like).
- *
- * <p><table>
- * <tr>
- * <td>Strongly reachable</td>
- * <td> <ul>
- * <li>There exists at least one path from the root set to the object that does not traverse any
- * instance of a {@code java.lang.ref.Reference} subclass.
- * </li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Softly reachable</td>
- * <td> <ul>
- * <li>The object is not strongly reachable.</li>
- * <li>There exists at least one path from the root set to the object that does traverse
- * a {@code java.lang.ref.SoftReference} instance, but no {@code java.lang.ref.WeakReference}
- * or {@code java.lang.ref.PhantomReference} instances.</li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Weakly reachable</td>
- * <td> <ul>
- * <li>The object is neither strongly nor softly reachable.</li>
- * <li>There exists at least one path from the root set to the object that does traverse a
- * {@code java.lang.ref.WeakReference} instance, but no {@code java.lang.ref.PhantomReference}
- * instances.</li>
- * </ul> </td>
- * </tr>
- *
- * <tr>
- * <td>Phantom-reachable</td>
- * <td> <ul>
- * <li>The object is neither strongly, softly, nor weakly reachable.</li>
- * <li>The object is referenced by a {@code java.lang.ref.PhantomReference} instance.</li>
- * <li>The object has already been finalized.</li>
- * </ul> </td>
- * </tr>
- * </table>
- */
-public abstract class Reference<T> {
-
- /**
- * The object to which this reference refers.
- * VM requirement: this field <em>must</em> be called "referent"
- * and be an object.
- */
- volatile T referent;
-
- /**
- * If non-null, the queue on which this reference will be enqueued
- * when the referent is appropriately reachable.
- * VM requirement: this field <em>must</em> be called "queue"
- * and be a java.lang.ref.ReferenceQueue.
- */
- volatile ReferenceQueue<? super T> queue;
-
- /**
- * Used internally by java.lang.ref.ReferenceQueue.
- * VM requirement: this field <em>must</em> be called "queueNext"
- * and be a java.lang.ref.Reference.
- */
- @SuppressWarnings("unchecked")
- volatile Reference queueNext;
-
- /**
- * Used internally by the VM. This field forms a circular and
- * singly linked list of reference objects discovered by the
- * garbage collector and awaiting processing by the reference
- * queue thread.
- *
- * @hide
- */
- public volatile Reference<?> pendingNext;
-
- /**
- * Constructs a new instance of this class.
- */
- Reference() {
- }
-
- Reference(T r, ReferenceQueue<? super T> q) {
- referent = r;
- queue = q;
- }
-
- /**
- * Makes the referent {@code null}. This does not force the reference
- * object to be enqueued.
- */
- public void clear() {
- referent = null;
- }
-
- /**
- * Adds an object to its reference queue.
- *
- * @return {@code true} if this call has caused the {@code Reference} to
- * become enqueued, or {@code false} otherwise
- *
- * @hide
- */
- public final synchronized boolean enqueueInternal() {
- if (queue != null && queueNext == null) {
- queue.enqueue(this);
- queue = null;
- return true;
- }
- return false;
- }
-
- /**
- * Forces the reference object to be enqueued if it has been associated with
- * a queue.
- *
- * @return {@code true} if this call has caused the {@code Reference} to
- * become enqueued, or {@code false} otherwise
- */
- public boolean enqueue() {
- return enqueueInternal();
- }
-
- /**
- * Returns the referent of the reference object.
- *
- * @return the referent to which reference refers, or {@code null} if the
- * object has been cleared.
- */
- public T get() {
- return referent;
- }
-
- /**
- * Checks whether the reference object has been enqueued.
- *
- * @return {@code true} if the {@code Reference} has been enqueued, {@code
- * false} otherwise
- */
- public boolean isEnqueued() {
- return queueNext != null;
- }
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java b/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
deleted file mode 100644
index f3d96af..0000000
--- a/libdvm/src/main/java/java/lang/reflect/AccessibleObject.java
+++ /dev/null
@@ -1,320 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Hashtable;
-import org.apache.harmony.kernel.vm.StringUtils;
-
-/**
- * {@code AccessibleObject} is the superclass of all member reflection classes
- * (Field, Constructor, Method). AccessibleObject provides the ability to toggle
- * a flag controlling access checks for these objects. By default, accessing a
- * member (for example, setting a field or invoking a method) checks the
- * validity of the access (for example, invoking a private method from outside
- * the defining class is prohibited) and throws IllegalAccessException if the
- * operation is not permitted. If the accessible flag is set to true, these
- * checks are omitted. This allows privileged code, such as Java object
- * serialization, object inspectors, and debuggers to have complete access to
- * objects.
- *
- * @see Field
- * @see Constructor
- * @see Method
- */
-public class AccessibleObject implements AnnotatedElement {
-
- /**
- * If true, object is accessible, bypassing normal access checks
- */
- boolean flag = false;
-
- // Holds a mapping from Java type names to native type codes.
- static Hashtable<String, String> trans;
-
- static {
- trans = new Hashtable<String, String>(9);
- trans.put("byte", "B");
- trans.put("char", "C");
- trans.put("short", "S");
- trans.put("int", "I");
- trans.put("long", "J");
- trans.put("float", "F");
- trans.put("double", "D");
- trans.put("void", "V");
- trans.put("boolean", "Z");
- }
-
- /**
- * Attempts to set the value of the accessible flag for all the objects in
- * the array provided. Setting this
- * flag to {@code false} will enable access checks, setting to {@code true}
- * will disable them.
- *
- * @param objects
- * the accessible objects
- * @param flag
- * the new value for the accessible flag
- *
- * @see #setAccessible(boolean)
- */
- public static void setAccessible(AccessibleObject[] objects, boolean flag) {
- for (AccessibleObject object : objects) {
- object.flag = flag;
- }
- }
-
- /**
- * Constructs a new {@code AccessibleObject} instance. {@code
- * AccessibleObject} instances can only be constructed by the virtual
- * machine.
- */
- protected AccessibleObject() {
- }
-
- /**
- * Indicates whether this object is accessible without access checks being
- * performed. Returns the accessible flag.
- *
- * @return {@code true} if this object is accessible without access
- * checks, {@code false} otherwise
- */
- public boolean isAccessible() {
- return flag;
- }
-
- /**
- * Attempts to set the value of the accessible flag. Setting this flag to
- * {@code false} will enable access checks, setting to {@code true} will
- * disable them.
- *
- * @param flag
- * the new value for the accessible flag
- */
- public void setAccessible(boolean flag) {
- this.flag = flag;
- }
-
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- throw new UnsupportedOperationException();
- }
-
- public Annotation[] getDeclaredAnnotations() {
- throw new UnsupportedOperationException();
- }
-
- public Annotation[] getAnnotations() {
- // for all but Class, getAnnotations == getDeclaredAnnotations
- return getDeclaredAnnotations();
- }
-
- public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
- throw new UnsupportedOperationException();
- }
-
- /**
- * Returns the signature for a class. This is the kind of signature used
- * internally by the JVM, with one-character codes representing the basic
- * types. It is not suitable for printing.
- *
- * @param clazz
- * the class for which a signature is required
- *
- * @return The signature as a string
- */
- String getSignature(Class<?> clazz) {
- String result = "";
- String nextType = clazz.getName();
-
- if(trans.containsKey(nextType)) {
- result = trans.get(nextType);
- } else {
- if(clazz.isArray()) {
- result = "[" + getSignature(clazz.getComponentType());
- } else {
- result = "L" + nextType + ";";
- }
- }
- return result;
- }
-
- /**
- * Returns a printable String consisting of the canonical names of the
- * classes contained in an array. The form is that used in parameter and
- * exception lists, that is, the class or type names are separated by
- * commas.
- *
- * @param types
- * the array of classes
- *
- * @return The String of names
- */
- String toString(Class<?>[] types) {
- StringBuilder result = new StringBuilder();
-
- if (types.length != 0) {
- appendTypeName(result, types[0]);
- for (int i = 1; i < types.length; i++) {
- result.append(',');
- appendTypeName(result, types[i]);
- }
- }
-
- return result.toString();
- }
-
- /**
- * Gets the Signature attribute for this instance. Returns {@code null}
- * if not found.
- */
- /*package*/ String getSignatureAttribute() {
- /*
- * Note: This method would have been declared abstract, but the
- * standard API lists this class as concrete.
- */
- throw new UnsupportedOperationException();
- }
-
- /**
- * Retrieve the signature attribute from an arbitrary class. This is
- * the same as Class.getSignatureAttribute(), but it can be used from
- * the java.lang.reflect package.
- */
- /*package*/ static String getClassSignatureAttribute(Class clazz) {
- Object[] annotation = getClassSignatureAnnotation(clazz);
-
- if (annotation == null) {
- return null;
- }
-
- return StringUtils.combineStrings(annotation);
- }
-
- /**
- * Retrieve the signature annotation from an arbitrary class. This is
- * the same as Class.getSignatureAttribute(), but it can be used from
- * the java.lang.reflect package.
- */
- private static native Object[] getClassSignatureAnnotation(Class clazz);
-
- /**
- * 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).
- */
- 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 specified array classes to the buffer. The array
- * elements may represent a simple type, a reference type or an array type.
- * Output format: java.lang.Object[], java.io.File, void
- *
- * @param types array of classes to print the names
- * @throws NullPointerException if any of the arguments is null
- */
- void appendArrayGenericType(StringBuilder sb, Type[] types) {
- if (types.length > 0) {
- appendGenericType(sb, types[0]);
- for (int i = 1; i < types.length; i++) {
- sb.append(',');
- appendGenericType(sb, types[i]);
- }
- }
- }
-
- /**
- * Appends the generic type representation to the buffer.
- *
- * @param sb buffer
- * @param obj the generic type which representation should be appended to the buffer
- *
- * @throws NullPointerException if any of the arguments is null
- */
- void appendGenericType(StringBuilder sb, Type obj) {
- if (obj instanceof TypeVariable) {
- sb.append(((TypeVariable)obj).getName());
- } else if (obj instanceof ParameterizedType) {
- sb.append(obj.toString());
- } else if (obj instanceof GenericArrayType) { //XXX: is it a working branch?
- Type simplified = ((GenericArrayType)obj).getGenericComponentType();
- appendGenericType(sb, simplified);
- sb.append("[]");
- } else if (obj instanceof Class) {
- Class c = ((Class<?>)obj);
- if (c.isArray()){
- String as[] = c.getName().split("\\[");
- int len = as.length-1;
- if (as[len].length() > 1){
- sb.append(as[len].substring(1, as[len].length()-1));
- } else {
- char ch = as[len].charAt(0);
- if (ch == 'I')
- sb.append("int");
- else if (ch == 'B')
- sb.append("byte");
- else if (ch == 'J')
- sb.append("long");
- else if (ch == 'F')
- sb.append("float");
- else if (ch == 'D')
- sb.append("double");
- else if (ch == 'S')
- sb.append("short");
- else if (ch == 'C')
- sb.append("char");
- else if (ch == 'Z')
- sb.append("boolean");
- else if (ch == 'V') //XXX: is it a working branch?
- sb.append("void");
- }
- for (int i = 0; i < len; i++){
- sb.append("[]");
- }
- } else {
- sb.append(c.getName());
- }
- }
- }
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Constructor.java b/libdvm/src/main/java/java/lang/reflect/Constructor.java
deleted file mode 100644
index acce44f..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Constructor.java
+++ /dev/null
@@ -1,466 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import libcore.util.EmptyArray;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.ListOfTypes;
-import libcore.reflect.Types;
-
-/**
- * This class represents a constructor. Information about the constructor can be
- * accessed, and the constructor can be invoked dynamically.
- *
- * @param <T> the class that declares this constructor
- */
-public final class Constructor<T> extends AccessibleObject implements GenericDeclaration,
- Member {
-
- Class<T> declaringClass;
-
- Class<?>[] parameterTypes;
-
- Class<?>[] exceptionTypes;
-
- ListOfTypes genericExceptionTypes;
- ListOfTypes genericParameterTypes;
- TypeVariable<Constructor<T>>[] formalTypeParameters;
- private volatile boolean genericTypesAreInitialized = false;
-
- private synchronized void initGenericTypes() {
- if (!genericTypesAreInitialized) {
- String signatureAttribute = getSignatureAttribute();
- GenericSignatureParser parser = new GenericSignatureParser(
- declaringClass.getClassLoader());
- parser.parseForConstructor(this, signatureAttribute, exceptionTypes);
- formalTypeParameters = parser.formalTypeParameters;
- genericParameterTypes = parser.parameterTypes;
- genericExceptionTypes = parser.exceptionTypes;
- genericTypesAreInitialized = true;
- }
- }
-
- int slot;
-
- private int methodDexIndex;
-
- /**
- * Prevent this class from being instantiated.
- */
- private Constructor(){
- //do nothing
- }
-
- /**
- * Creates an instance of the class. Only called from native code, thus
- * private.
- *
- * @param declaringClass
- * the class this constructor object belongs to
- * @param ptypes
- * the parameter types of the constructor
- * @param extypes
- * the exception types of the constructor
- * @param slot
- * the slot of the constructor inside the VM class structure
- */
- 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() {
- Object[] annotation = Method.getSignatureAnnotation(declaringClass, slot);
-
- if (annotation == null) {
- return null;
- }
-
- return StringUtils.combineStrings(annotation);
- }
-
- public TypeVariable<Constructor<T>>[] getTypeParameters() {
- initGenericTypes();
- return formalTypeParameters.clone();
- }
-
- /**
- * Returns the string representation of the constructor's declaration,
- * including the type parameters.
- *
- * @return the string representation of the constructor's declaration
- */
- public String toGenericString() {
- StringBuilder sb = new StringBuilder(80);
- initGenericTypes();
- // append modifiers if any
- int modifier = getModifiers();
- if (modifier != 0) {
- sb.append(Modifier.toString(modifier & ~Modifier.VARARGS)).append(' ');
- }
- // append type parameters
- if (formalTypeParameters != null && formalTypeParameters.length > 0) {
- sb.append('<');
- for (int i = 0; i < formalTypeParameters.length; i++) {
- appendGenericType(sb, formalTypeParameters[i]);
- if (i < formalTypeParameters.length - 1) {
- sb.append(",");
- }
- }
- sb.append("> ");
- }
- // append constructor name
- appendTypeName(sb, getDeclaringClass());
- // append parameters
- sb.append('(');
- appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
- sb.append(')');
- // append exceptions if any
- Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
- if (genericExceptionTypeArray.length > 0) {
- sb.append(" throws ");
- appendArrayGenericType(sb, genericExceptionTypeArray);
- }
- return sb.toString();
- }
-
- /**
- * Returns the generic parameter types as an array of {@code Type}
- * instances, in declaration order. If this constructor has no generic
- * parameters, an empty array is returned.
- *
- * @return the parameter types
- *
- * @throws GenericSignatureFormatError
- * if the generic constructor signature is invalid
- * @throws TypeNotPresentException
- * if any parameter type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if any parameter type points to a type that cannot be
- * instantiated for some reason
- */
- public Type[] getGenericParameterTypes() {
- initGenericTypes();
- return Types.getTypeArray(genericParameterTypes, true);
- }
-
- /**
- * Returns the exception types as an array of {@code Type} instances. If
- * this constructor has no declared exceptions, an empty array will be
- * returned.
- *
- * @return an array of generic exception types
- *
- * @throws GenericSignatureFormatError
- * if the generic constructor signature is invalid
- * @throws TypeNotPresentException
- * if any exception type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if any exception type points to a type that cannot be
- * instantiated for some reason
- */
- public Type[] getGenericExceptionTypes() {
- initGenericTypes();
- return Types.getTypeArray(genericExceptionTypes, true);
- }
-
- @Override
- public Annotation[] getDeclaredAnnotations() {
- return Method.getDeclaredAnnotations(declaringClass, slot);
- }
-
- @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return Method.getAnnotation(declaringClass, slot, annotationType);
- }
-
- @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return Method.isAnnotationPresent(declaringClass, slot, annotationType);
- }
-
- /**
- * Returns an array of arrays that represent the annotations of the formal
- * parameters of this constructor. If there are no parameters on this
- * constructor, then an empty array is returned. If there are no annotations
- * set, then an array of empty arrays is returned.
- *
- * @return an array of arrays of {@code Annotation} instances
- */
- public Annotation[][] getParameterAnnotations() {
- Annotation[][] parameterAnnotations
- = Method.getParameterAnnotations(declaringClass, slot);
- if (parameterAnnotations.length == 0) {
- return Method.noAnnotations(parameterTypes.length);
- }
- return parameterAnnotations;
- }
-
- /**
- * Indicates whether or not this constructor takes a variable number of
- * arguments.
- *
- * @return {@code true} if a vararg is declare, otherwise
- * {@code false}
- */
- public boolean isVarArgs() {
- int mods = Method.getMethodModifiers(declaringClass, slot);
- return (mods & Modifier.VARARGS) != 0;
- }
-
- /**
- * Indicates whether or not this constructor is synthetic (artificially
- * introduced by the compiler).
- *
- * @return {@code true} if this constructor is synthetic, {@code false}
- * otherwise
- */
- public boolean isSynthetic() {
- int mods = Method.getMethodModifiers(declaringClass, slot);
- return (mods & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Indicates whether or not the specified {@code object} is equal to this
- * constructor. To be equal, the specified object must be an instance
- * of {@code Constructor} with the same declaring class and parameter types
- * as this constructor.
- *
- * @param object
- * the object to compare
- *
- * @return {@code true} if the specified object is equal to this
- * constructor, {@code false} otherwise
- *
- * @see #hashCode
- */
- @Override
- public boolean equals(Object object) {
- return object instanceof Constructor && toString().equals(object.toString());
- }
-
- /**
- * Returns the class that declares this constructor.
- *
- * @return the declaring class
- */
- public Class<T> getDeclaringClass() {
- return declaringClass;
- }
-
- /**
- * Returns the exception types as an array of {@code Class} instances. If
- * this constructor has no declared exceptions, an empty array will be
- * returned.
- *
- * @return the declared exception classes
- */
- public Class<?>[] getExceptionTypes() {
- if (exceptionTypes == null) {
- return EmptyArray.CLASS;
- }
- return exceptionTypes.clone();
- }
-
- /**
- * Returns the modifiers for this constructor. The {@link Modifier} class
- * should be used to decode the result.
- *
- * @return the modifiers for this constructor
- *
- * @see Modifier
- */
- public int getModifiers() {
- return Method.getMethodModifiers(declaringClass, slot);
- }
-
- /**
- * Returns the name of this constructor.
- *
- * @return the name of this constructor
- */
- public String getName() {
- return declaringClass.getName();
- }
-
- /**
- * Returns an array of the {@code Class} objects associated with the
- * parameter types of this constructor. If the constructor was declared with
- * no parameters, an empty array will be returned.
- *
- * @return the parameter types
- */
- public Class<?>[] getParameterTypes() {
- return parameterTypes.clone();
- }
-
- /**
- * Returns the constructor's signature in non-printable form. This is called
- * (only) from IO native code and needed for deriving the serialVersionUID
- * of the class
- *
- * @return the constructor's signature
- */
- @SuppressWarnings("unused")
- private String getSignature() {
- StringBuilder result = new StringBuilder();
-
- result.append('(');
- for (int i = 0; i < parameterTypes.length; i++) {
- result.append(getSignature(parameterTypes[i]));
- }
- result.append(")V");
-
- return result.toString();
- }
-
- /**
- * Returns an integer hash code for this constructor. Constructors which are
- * equal return the same value for this method. The hash code for a
- * Constructor is the hash code of the name of the declaring class.
- *
- * @return the hash code
- *
- * @see #equals
- */
- @Override
- public int hashCode() {
- return declaringClass.getName().hashCode();
- }
-
- /**
- * Returns a new instance of the declaring class, initialized by dynamically
- * invoking the constructor represented by this {@code Constructor} object.
- * This reproduces the effect of {@code new declaringClass(arg1, arg2, ... ,
- * argN)} This method performs the following:
- * <ul>
- * <li>A new instance of the declaring class is created. If the declaring
- * class cannot be instantiated (i.e. abstract class, an interface, an array
- * type, or a primitive type) then an InstantiationException is thrown.</li>
- * <li>If this Constructor object is enforcing access control (see
- * {@link AccessibleObject}) and this constructor is not accessible from the
- * current context, an IllegalAccessException is thrown.</li>
- * <li>If the number of arguments passed and the number of parameters do not
- * match, an IllegalArgumentException is thrown.</li>
- * <li>For each argument passed:
- * <ul>
- * <li>If the corresponding parameter type is a primitive type, the argument
- * is unboxed. If the unboxing fails, an IllegalArgumentException is
- * thrown.</li>
- * <li>If the resulting argument cannot be converted to the parameter type
- * via a widening conversion, an IllegalArgumentException is thrown.</li>
- * </ul>
- * <li>The constructor represented by this {@code Constructor} object is
- * then invoked. If an exception is thrown during the invocation, it is
- * caught and wrapped in an InvocationTargetException. This exception is
- * then thrown. If the invocation completes normally, the newly initialized
- * object is returned.
- * </ul>
- *
- * @param args
- * the arguments to the constructor
- *
- * @return the new, initialized, object
- *
- * @throws InstantiationException
- * if the class cannot be instantiated
- * @throws IllegalAccessException
- * if this constructor is not accessible
- * @throws IllegalArgumentException
- * if an incorrect number of arguments are passed, or an
- * argument could not be converted by a widening conversion
- * @throws InvocationTargetException
- * if an exception was thrown by the invoked constructor
- *
- * @see AccessibleObject
- */
- public T newInstance(Object... args) throws InstantiationException, IllegalAccessException,
- IllegalArgumentException, InvocationTargetException {
- return constructNative (args, declaringClass, parameterTypes, slot, flag);
- }
-
- private native T constructNative(Object[] args, Class<T> declaringClass,
- Class<?>[] parameterTypes, int slot,
- boolean noAccessCheck) throws InstantiationException, IllegalAccessException,
- InvocationTargetException;
-
- /**
- * Returns a string containing a concise, human-readable description of this
- * constructor. The format of the string is:
- *
- * <ol>
- * <li>modifiers (if any)
- * <li>declaring class name
- * <li>'('
- * <li>parameter types, separated by ',' (if any)
- * <li>')'
- * <li>'throws' plus exception types, separated by ',' (if any)
- * </ol>
- *
- * For example:
- * {@code public String(byte[],String) throws UnsupportedEncodingException}
- *
- * @return a printable representation for this constructor
- */
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
-
- if (result.length() != 0)
- result.append(' ');
- result.append(declaringClass.getName());
- result.append("(");
- result.append(toString(parameterTypes));
- result.append(")");
- if (exceptionTypes != null && exceptionTypes.length != 0) {
- result.append(" throws ");
- result.append(toString(exceptionTypes));
- }
-
- return result.toString();
- }
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Field.java b/libdvm/src/main/java/java/lang/reflect/Field.java
deleted file mode 100644
index fa8e5e7..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Field.java
+++ /dev/null
@@ -1,931 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Comparator;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.Types;
-
-/**
- * This class represents a field. Information about the field can be accessed,
- * and the field's value can be accessed dynamically.
- */
-public final class Field extends AccessibleObject implements Member {
-
- /**
- * Orders fields by their name and declaring class.
- *
- * @hide
- */
- public static final Comparator<Field> ORDER_BY_NAME_AND_DECLARING_CLASS
- = new Comparator<Field>() {
- @Override public int compare(Field a, Field b) {
- int comparison = a.name.compareTo(b.name);
- if (comparison != 0) {
- return comparison;
- }
-
- return a.getDeclaringClass().getName().compareTo(b.getDeclaringClass().getName());
- }
- };
-
- private Class<?> declaringClass;
-
- private Class<?> type;
-
- private Type genericType;
-
- private volatile boolean genericTypesAreInitialized = false;
-
- private String name;
-
- private int slot;
-
- private final int fieldDexIndex;
-
- private static final char TYPE_BOOLEAN = 'Z';
-
- private static final char TYPE_BYTE = 'B';
-
- private static final char TYPE_CHAR = 'C';
-
- private static final char TYPE_SHORT = 'S';
-
- private static final char TYPE_INTEGER = 'I';
-
- private static final char TYPE_FLOAT = 'F';
-
- private static final char TYPE_LONG = 'J';
-
- private static final char TYPE_DOUBLE = 'D';
-
- 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() {
- if (!genericTypesAreInitialized) {
- String signatureAttribute = getSignatureAttribute();
- GenericSignatureParser parser = new GenericSignatureParser(
- declaringClass.getClassLoader());
- parser.parseForField(this.declaringClass, signatureAttribute);
- genericType = parser.fieldType;
- if (genericType == null) {
- genericType = getType();
- }
- genericTypesAreInitialized = true;
- }
- }
-
- /** {@inheritDoc} */
- @Override
- /* package */String getSignatureAttribute() {
- Object[] annotation = getSignatureAnnotation(declaringClass, slot);
-
- if (annotation == null) {
- return null;
- }
-
- return StringUtils.combineStrings(annotation);
- }
-
- /**
- * Get the Signature annotation for this field. Returns null if not found.
- */
- native private Object[] getSignatureAnnotation(Class declaringClass, int slot);
-
- /**
- * Indicates whether or not this field is synthetic.
- *
- * @return {@code true} if this field is synthetic, {@code false} otherwise
- */
- public boolean isSynthetic() {
- int flags = getFieldModifiers(declaringClass, slot);
- return (flags & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Returns the string representation of this field, including the field's
- * generic type.
- *
- * @return the string representation of this field
- */
- public String toGenericString() {
- StringBuilder sb = new StringBuilder(80);
- // append modifiers if any
- int modifier = getModifiers();
- if (modifier != 0) {
- sb.append(Modifier.toString(modifier)).append(' ');
- }
- // append generic type
- appendGenericType(sb, getGenericType());
- sb.append(' ');
- // append full field name
- sb.append(getDeclaringClass().getName()).append('.').append(getName());
- return sb.toString();
- }
-
- /**
- * Indicates whether or not this field is an enumeration constant.
- *
- * @return {@code true} if this field is an enumeration constant, {@code
- * false} otherwise
- */
- public boolean isEnumConstant() {
- int flags = getFieldModifiers(declaringClass, slot);
- return (flags & Modifier.ENUM) != 0;
- }
-
- /**
- * Returns the generic type of this field.
- *
- * @return the generic type
- * @throws GenericSignatureFormatError
- * if the generic field signature is invalid
- * @throws TypeNotPresentException
- * if the generic type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if the generic type points to a type that cannot be
- * instantiated for some reason
- */
- public Type getGenericType() {
- initGenericType();
- return Types.getType(genericType);
- }
-
- @Override public Annotation[] getDeclaredAnnotations() {
- return getDeclaredAnnotations(declaringClass, slot);
- }
- private static native Annotation[] getDeclaredAnnotations(Class declaringClass, int slot);
-
- @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return getAnnotation(declaringClass, slot, annotationType);
- }
- private static native <A extends Annotation> A getAnnotation(
- Class<?> declaringClass, int slot, Class<A> annotationType);
-
- @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return isAnnotationPresent(declaringClass, slot, annotationType);
- }
- private static native boolean isAnnotationPresent(
- Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
-
- /**
- * Indicates whether or not the specified {@code object} is equal to this
- * field. To be equal, the specified object must be an instance of
- * {@code Field} with the same declaring class, type and name as this field.
- *
- * @param object
- * the object to compare
- * @return {@code true} if the specified object is equal to this method,
- * {@code false} otherwise
- * @see #hashCode
- */
- @Override
- public boolean equals(Object object) {
- return object instanceof Field && toString().equals(object.toString());
- }
-
- /**
- * Returns the value of the field in the specified object. This reproduces
- * the effect of {@code object.fieldName}
- *
- * <p>If the type of this field is a primitive type, the field value is
- * automatically boxed.
- *
- * <p>If this field is static, the object argument is ignored.
- * Otherwise, if the object is null, a NullPointerException is thrown. If
- * the object is not an instance of the declaring class of the method, an
- * IllegalArgumentException is thrown.
- *
- * <p>If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value, possibly boxed
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public Object get(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getField(object, declaringClass, type, slot, flag);
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code
- * boolean}. This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public boolean getBoolean(Object object) throws IllegalAccessException,
- IllegalArgumentException {
- return getZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN);
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code byte}.
- * This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public byte getByte(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getBField(object, declaringClass, type, slot, flag, TYPE_BYTE);
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code char}.
- * This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public char getChar(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getCField(object, declaringClass, type, slot, flag, TYPE_CHAR);
- }
-
- /**
- * Returns the class that declares this field.
- *
- * @return the declaring class
- */
- public Class<?> getDeclaringClass() {
- return declaringClass;
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code
- * double}. This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public double getDouble(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE);
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code float}
- * . This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public float getFloat(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getFField(object, declaringClass, type, slot, flag, TYPE_FLOAT);
- }
-
- /**
- * Returns the value of the field in the specified object as an {@code int}.
- * This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public int getInt(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getIField(object, declaringClass, type, slot, flag, TYPE_INTEGER);
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code long}.
- * This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public long getLong(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getJField(object, declaringClass, type, slot, flag, TYPE_LONG);
- }
-
- /**
- * Returns the modifiers for this field. The {@link Modifier} class should
- * be used to decode the result.
- *
- * @return the modifiers for this field
- * @see Modifier
- */
- public int getModifiers() {
- return getFieldModifiers(declaringClass, slot);
- }
-
- private native int getFieldModifiers(Class<?> declaringClass, int slot);
-
- /**
- * Returns the name of this field.
- *
- * @return the name of this field
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns the value of the field in the specified object as a {@code short}
- * . This reproduces the effect of {@code object.fieldName}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * @param object
- * the object to access
- * @return the field value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public short getShort(Object object) throws IllegalAccessException, IllegalArgumentException {
- return getSField(object, declaringClass, type, slot, flag, TYPE_SHORT);
- }
-
- /**
- * Returns the constructor's signature in non-printable form. This is called
- * (only) from IO native code and needed for deriving the serialVersionUID
- * of the class
- *
- * @return the constructor's signature.
- */
- @SuppressWarnings("unused")
- private String getSignature() {
- return getSignature(type);
- }
-
- /**
- * Return the {@link Class} associated with the type of this field.
- *
- * @return the type of this field
- */
- public Class<?> getType() {
- return type;
- }
-
- /**
- * Returns an integer hash code for this field. Objects which are equal
- * return the same value for this method.
- * <p>
- * The hash code for a Field is the exclusive-or combination of the hash
- * code of the field's name and the hash code of the name of its declaring
- * class.
- *
- * @return the hash code for this field
- * @see #equals
- */
- @Override
- public int hashCode() {
- return name.hashCode() ^ getDeclaringClass().getName().hashCode();
- }
-
- /**
- * Sets the value of the field in the specified object to the value. This
- * reproduces the effect of {@code object.fieldName = value}
- *
- * <p>If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- *
- * <p>If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- *
- * <p>If the field type is a primitive type, the value is automatically
- * unboxed. If the unboxing fails, an IllegalArgumentException is thrown. If
- * the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void set(Object object, Object value) throws IllegalAccessException,
- IllegalArgumentException {
- setField(object, declaringClass, type, slot, flag, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code
- * boolean} value. This reproduces the effect of {@code object.fieldName =
- * value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setBoolean(Object object, boolean value) throws IllegalAccessException,
- IllegalArgumentException {
- setZField(object, declaringClass, type, slot, flag, TYPE_BOOLEAN, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code byte}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setByte(Object object, byte value) throws IllegalAccessException,
- IllegalArgumentException {
- setBField(object, declaringClass, type, slot, flag, TYPE_BYTE, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code char}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setChar(Object object, char value) throws IllegalAccessException,
- IllegalArgumentException {
- setCField(object, declaringClass, type, slot, flag, TYPE_CHAR, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code double}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setDouble(Object object, double value) throws IllegalAccessException,
- IllegalArgumentException {
- setDField(object, declaringClass, type, slot, flag, TYPE_DOUBLE, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code float}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setFloat(Object object, float value) throws IllegalAccessException,
- IllegalArgumentException {
- setFField(object, declaringClass, type, slot, flag, TYPE_FLOAT, value);
- }
-
- /**
- * Set the value of the field in the specified object to the {@code int}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setInt(Object object, int value) throws IllegalAccessException,
- IllegalArgumentException {
- setIField(object, declaringClass, type, slot, flag, TYPE_INTEGER, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code long}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setLong(Object object, long value) throws IllegalAccessException,
- IllegalArgumentException {
- setJField(object, declaringClass, type, slot, flag, TYPE_LONG, value);
- }
-
- /**
- * Sets the value of the field in the specified object to the {@code short}
- * value. This reproduces the effect of {@code object.fieldName = value}
- * <p>
- * If this field is static, the object argument is ignored.
- * Otherwise, if the object is {@code null}, a NullPointerException is
- * thrown. If the object is not an instance of the declaring class of the
- * method, an IllegalArgumentException is thrown.
- * <p>
- * If this Field object is enforcing access control (see AccessibleObject)
- * and this field is not accessible from the current context, an
- * IllegalAccessException is thrown.
- * <p>
- * If the value cannot be converted to the field type via a widening
- * conversion, an IllegalArgumentException is thrown.
- *
- * @param object
- * the object to access
- * @param value
- * the new value
- * @throws NullPointerException
- * if the object is {@code null} and the field is non-static
- * @throws IllegalArgumentException
- * if the object is not compatible with the declaring class
- * @throws IllegalAccessException
- * if this field is not accessible
- */
- public void setShort(Object object, short value) throws IllegalAccessException,
- IllegalArgumentException {
- setSField(object, declaringClass, type, slot, flag, TYPE_SHORT, value);
- }
-
- /**
- * Returns a string containing a concise, human-readable description of this
- * field.
- * <p>
- * The format of the string is:
- * <ol>
- * <li>modifiers (if any)
- * <li>type
- * <li>declaring class name
- * <li>'.'
- * <li>field name
- * </ol>
- * <p>
- * For example: {@code public static java.io.InputStream
- * java.lang.System.in}
- *
- * @return a printable representation for this field
- */
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
- if (result.length() != 0) {
- result.append(' ');
- }
- appendTypeName(result, type);
- result.append(' ');
- appendTypeName(result, declaringClass);
- result.append('.');
- result.append(name);
- return result.toString();
- }
-
- private native Object getField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck) throws IllegalAccessException;
-
- private native double getDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native int getIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native long getJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native boolean getZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native float getFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native char getCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native short getSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native byte getBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor) throws IllegalAccessException;
-
- private native void setField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, Object value) throws IllegalAccessException;
-
- private native void setDField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, double v) throws IllegalAccessException;
-
- private native void setIField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, int i) throws IllegalAccessException;
-
- private native void setJField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, long j) throws IllegalAccessException;
-
- private native void setZField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, boolean z) throws IllegalAccessException;
-
- private native void setFField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, float f) throws IllegalAccessException;
-
- private native void setCField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, char c) throws IllegalAccessException;
-
- private native void setSField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, short s) throws IllegalAccessException;
-
- private native void setBField(Object o, Class<?> declaringClass, Class<?> type, int slot,
- boolean noAccessCheck, char descriptor, byte b) throws IllegalAccessException;
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Method.java b/libdvm/src/main/java/java/lang/reflect/Method.java
deleted file mode 100644
index f8efbf4..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Method.java
+++ /dev/null
@@ -1,587 +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.
- */
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.lang.reflect;
-
-import java.lang.annotation.Annotation;
-import java.util.Arrays;
-import java.util.Comparator;
-import libcore.util.EmptyArray;
-import org.apache.harmony.kernel.vm.StringUtils;
-import libcore.reflect.GenericSignatureParser;
-import libcore.reflect.ListOfTypes;
-import libcore.reflect.Types;
-
-/**
- * This class represents a method. Information about the method can be accessed,
- * and the method can be invoked dynamically.
- */
-public final class Method extends AccessibleObject implements GenericDeclaration, Member {
-
- /**
- * Orders methods by their name, parameters and return type.
- *
- * @hide
- */
- public static final Comparator<Method> ORDER_BY_SIGNATURE = new Comparator<Method>() {
- public int compare(Method a, Method b) {
- int comparison = a.name.compareTo(b.name);
- if (comparison != 0) {
- return comparison;
- }
-
- Class<?>[] aParameters = a.parameterTypes;
- Class<?>[] bParameters = b.parameterTypes;
- int length = Math.min(aParameters.length, bParameters.length);
- for (int i = 0; i < length; i++) {
- comparison = aParameters[i].getName().compareTo(bParameters[i].getName());
- if (comparison != 0) {
- return comparison;
- }
- }
-
- if (aParameters.length != bParameters.length) {
- return aParameters.length - bParameters.length;
- }
-
- // this is necessary for methods that have covariant return types.
- return a.getReturnType().getName().compareTo(b.getReturnType().getName());
- }
- };
-
- private int slot;
-
- private final int methodDexIndex;
-
- private Class<?> declaringClass;
-
- private String name;
-
- private Class<?>[] parameterTypes;
-
- private Class<?>[] exceptionTypes;
-
- private Class<?> returnType;
-
- private ListOfTypes genericExceptionTypes;
- private ListOfTypes genericParameterTypes;
- private Type genericReturnType;
- private TypeVariable<Method>[] formalTypeParameters;
- private volatile boolean genericTypesAreInitialized = false;
-
- private synchronized void initGenericTypes() {
- if (!genericTypesAreInitialized) {
- String signatureAttribute = getSignatureAttribute();
- GenericSignatureParser parser = new GenericSignatureParser(
- declaringClass.getClassLoader());
- parser.parseForMethod(this, signatureAttribute, exceptionTypes);
- formalTypeParameters = parser.formalTypeParameters;
- genericParameterTypes = parser.parameterTypes;
- genericExceptionTypes = parser.exceptionTypes;
- genericReturnType = parser.returnType;
- genericTypesAreInitialized = true;
- }
- }
-
- 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() {
- initGenericTypes();
- return formalTypeParameters.clone();
- }
-
- /** {@inheritDoc} */
- @Override /*package*/ String getSignatureAttribute() {
- Object[] annotation = getSignatureAnnotation(declaringClass, slot);
-
- if (annotation == null) {
- return null;
- }
-
- return StringUtils.combineStrings(annotation);
- }
-
- /**
- * Returns the Signature annotation for this method. Returns {@code null} if
- * not found.
- */
- static native Object[] getSignatureAnnotation(Class declaringClass, int slot);
-
- /**
- * Returns the string representation of the method's declaration, including
- * the type parameters.
- *
- * @return the string representation of this method
- */
- public String toGenericString() {
- StringBuilder sb = new StringBuilder(80);
-
- initGenericTypes();
-
- // append modifiers if any
- int modifier = getModifiers();
- if (modifier != 0) {
- sb.append(Modifier.toString(modifier & ~(Modifier.BRIDGE +
- Modifier.VARARGS))).append(' ');
- }
- // append type parameters
- if (formalTypeParameters != null && formalTypeParameters.length > 0) {
- sb.append('<');
- for (int i = 0; i < formalTypeParameters.length; i++) {
- appendGenericType(sb, formalTypeParameters[i]);
- if (i < formalTypeParameters.length - 1) {
- sb.append(",");
- }
- }
- sb.append("> ");
- }
- // append return type
- appendGenericType(sb, Types.getType(genericReturnType));
- sb.append(' ');
- // append method name
- appendTypeName(sb, getDeclaringClass());
- sb.append(".").append(getName());
- // append parameters
- sb.append('(');
- appendArrayGenericType(sb, Types.getTypeArray(genericParameterTypes, false));
- sb.append(')');
- // append exceptions if any
- Type[] genericExceptionTypeArray = Types.getTypeArray(genericExceptionTypes, false);
- if (genericExceptionTypeArray.length > 0) {
- sb.append(" throws ");
- appendArrayGenericType(sb, genericExceptionTypeArray);
- }
- return sb.toString();
- }
-
- /**
- * Returns the parameter types as an array of {@code Type} instances, in
- * declaration order. If this method has no parameters, an empty array is
- * returned.
- *
- * @return the parameter types
- *
- * @throws GenericSignatureFormatError
- * if the generic method signature is invalid
- * @throws TypeNotPresentException
- * if any parameter type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if any parameter type points to a type that cannot be
- * instantiated for some reason
- */
- public Type[] getGenericParameterTypes() {
- initGenericTypes();
- return Types.getTypeArray(genericParameterTypes, true);
- }
-
- /**
- * Returns the exception types as an array of {@code Type} instances. If
- * this method has no declared exceptions, an empty array will be returned.
- *
- * @return an array of generic exception types
- *
- * @throws GenericSignatureFormatError
- * if the generic method signature is invalid
- * @throws TypeNotPresentException
- * if any exception type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if any exception type points to a type that cannot be
- * instantiated for some reason
- */
- public Type[] getGenericExceptionTypes() {
- initGenericTypes();
- return Types.getTypeArray(genericExceptionTypes, true);
- }
-
- /**
- * Returns the return type of this method as a {@code Type} instance.
- *
- * @return the return type of this method
- *
- * @throws GenericSignatureFormatError
- * if the generic method signature is invalid
- * @throws TypeNotPresentException
- * if the return type points to a missing type
- * @throws MalformedParameterizedTypeException
- * if the return type points to a type that cannot be
- * instantiated for some reason
- */
- public Type getGenericReturnType() {
- initGenericTypes();
- return Types.getType(genericReturnType);
- }
-
- @Override
- public Annotation[] getDeclaredAnnotations() {
- return getDeclaredAnnotations(declaringClass, slot);
- }
- static native Annotation[] getDeclaredAnnotations(Class<?> declaringClass, int slot);
-
- @Override public <A extends Annotation> A getAnnotation(Class<A> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return getAnnotation(declaringClass, slot, annotationType);
- }
- static native <A extends Annotation> A getAnnotation(
- Class<?> declaringClass, int slot, Class<A> annotationType);
-
- @Override public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- if (annotationType == null) {
- throw new NullPointerException("annotationType == null");
- }
- return isAnnotationPresent(declaringClass, slot, annotationType);
- }
- static native boolean isAnnotationPresent(
- Class<?> declaringClass, int slot, Class<? extends Annotation> annotationType);
-
- private static final Annotation[] NO_ANNOTATIONS = new Annotation[0];
-
- /**
- * Creates an array of empty Annotation arrays.
- */
- /*package*/ static Annotation[][] noAnnotations(int size) {
- Annotation[][] annotations = new Annotation[size][];
- for (int i = 0; i < size; i++) {
- annotations[i] = NO_ANNOTATIONS;
- }
- return annotations;
- }
-
- /**
- * Returns an array of arrays that represent the annotations of the formal
- * parameters of this method. If there are no parameters on this method,
- * then an empty array is returned. If there are no annotations set, then
- * and array of empty arrays is returned.
- *
- * @return an array of arrays of {@code Annotation} instances
- */
- public Annotation[][] getParameterAnnotations() {
- Annotation[][] parameterAnnotations
- = getParameterAnnotations(declaringClass, slot);
- if (parameterAnnotations.length == 0) {
- return noAnnotations(parameterTypes.length);
- }
- return parameterAnnotations;
- }
-
- static native Annotation[][] getParameterAnnotations(Class declaringClass, int slot);
-
- /**
- * Indicates whether or not this method takes a variable number argument.
- *
- * @return {@code true} if a vararg is declared, {@code false} otherwise
- */
- public boolean isVarArgs() {
- int modifiers = getMethodModifiers(declaringClass, slot);
- return (modifiers & Modifier.VARARGS) != 0;
- }
-
- /**
- * Indicates whether or not this method is a bridge.
- *
- * @return {@code true} if this method is a bridge, {@code false} otherwise
- */
- public boolean isBridge() {
- int modifiers = getMethodModifiers(declaringClass, slot);
- return (modifiers & Modifier.BRIDGE) != 0;
- }
-
- /**
- * Indicates whether or not this method is synthetic.
- *
- * @return {@code true} if this method is synthetic, {@code false} otherwise
- */
- public boolean isSynthetic() {
- int modifiers = getMethodModifiers(declaringClass, slot);
- return (modifiers & Modifier.SYNTHETIC) != 0;
- }
-
- /**
- * Returns the default value for the annotation member represented by this
- * method.
- *
- * @return the default value, or {@code null} if none
- *
- * @throws TypeNotPresentException
- * if this annotation member is of type {@code Class} and no
- * definition can be found
- */
- public Object getDefaultValue() {
- return getDefaultValue(declaringClass, slot);
- }
- native private Object getDefaultValue(Class declaringClass, int slot);
-
- /**
- * Indicates whether or not the specified {@code object} is equal to this
- * method. To be equal, the specified object must be an instance
- * of {@code Method} with the same declaring class and parameter types
- * as this method.
- *
- * @param object
- * the object to compare
- *
- * @return {@code true} if the specified object is equal to this
- * method, {@code false} otherwise
- *
- * @see #hashCode
- */
- @Override
- public boolean equals(Object object) {
- if (this == object) {
- return true;
- }
- if (!(object instanceof Method)) {
- return false;
- }
- Method rhs = (Method) object;
- // We don't compare exceptionTypes because two methods
- // can't differ only by their declared exceptions.
- return declaringClass.equals(rhs.declaringClass) &&
- name.equals(rhs.name) &&
- getModifiers() == rhs.getModifiers() &&
- returnType.equals(rhs.returnType) &&
- Arrays.equals(parameterTypes, rhs.parameterTypes);
- }
-
- /**
- * Returns the class that declares this method.
- *
- * @return the declaring class
- */
- public Class<?> getDeclaringClass() {
- return declaringClass;
- }
-
- /**
- * Returns the exception types as an array of {@code Class} instances. If
- * this method has no declared exceptions, an empty array is returned.
- *
- * @return the declared exception classes
- */
- public Class<?>[] getExceptionTypes() {
- if (exceptionTypes == null) {
- return EmptyArray.CLASS;
- }
- return exceptionTypes.clone();
- }
-
- /**
- * Returns the modifiers for this method. The {@link Modifier} class should
- * be used to decode the result.
- *
- * @return the modifiers for this method
- *
- * @see Modifier
- */
- public int getModifiers() {
- return getMethodModifiers(declaringClass, slot);
- }
-
- static native int getMethodModifiers(Class<?> declaringClass, int slot);
-
- /**
- * Returns the name of the method represented by this {@code Method}
- * instance.
- *
- * @return the name of this method
- */
- public String getName() {
- return name;
- }
-
- /**
- * Returns an array of {@code Class} objects associated with the parameter
- * types of this method. If the method was declared with no parameters, an
- * empty array will be returned.
- *
- * @return the parameter types
- */
- public Class<?>[] getParameterTypes() {
- return parameterTypes.clone();
- }
-
- /**
- * Returns the {@code Class} associated with the return type of this
- * method.
- *
- * @return the return type
- */
- public Class<?> getReturnType() {
- return returnType;
- }
-
- /**
- * Returns an integer hash code for this method. Objects which are equal
- * return the same value for this method. The hash code for this Method is
- * the hash code of the name of this method.
- *
- * @return hash code for this method
- *
- * @see #equals
- */
- @Override
- public int hashCode() {
- return name.hashCode();
- }
-
- /**
- * Returns the result of dynamically invoking this method. Equivalent to
- * {@code receiver.methodName(arg1, arg2, ... , argN)}.
- *
- * <p>If the method is static, the receiver argument is ignored (and may be null).
- *
- * <p>If the method takes no arguments, you can pass {@code (Object[]) null} instead of
- * allocating an empty array.
- *
- * <p>If you're calling a varargs method, you need to pass an {@code Object[]} for the
- * varargs parameter: that conversion is usually done in {@code javac}, not the VM, and
- * the reflection machinery does not do this for you. (It couldn't, because it would be
- * ambiguous.)
- *
- * <p>Reflective method invocation follows the usual process for method lookup.
- *
- * <p>If an exception is thrown during the invocation it is caught and
- * wrapped in an InvocationTargetException. This exception is then thrown.
- *
- * <p>If the invocation completes normally, the return value itself is
- * returned. If the method is declared to return a primitive type, the
- * return value is boxed. If the return type is void, null is returned.
- *
- * @param receiver
- * the object on which to call this method (or null for static methods)
- * @param args
- * the arguments to the method
- * @return the result
- *
- * @throws NullPointerException
- * if {@code receiver == null} for a non-static method
- * @throws IllegalAccessException
- * if this method is not accessible (see {@link AccessibleObject})
- * @throws IllegalArgumentException
- * if the number of arguments doesn't match the number of parameters, the receiver
- * is incompatible with the declaring class, or an argument could not be unboxed
- * or converted by a widening conversion to the corresponding parameter type
- * @throws InvocationTargetException
- * if an exception was thrown by the invoked method
- */
- public Object invoke(Object receiver, Object... args)
- throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
- if (args == null) {
- args = EmptyArray.OBJECT;
- }
- return invokeNative(receiver, args, declaringClass, parameterTypes, returnType, slot, flag);
- }
-
- private native Object invokeNative(Object obj, Object[] args, Class<?> declaringClass,
- Class<?>[] parameterTypes, Class<?> returnType, int slot, boolean noAccessCheck)
- throws IllegalAccessException, IllegalArgumentException,
- InvocationTargetException;
-
- /**
- * Returns a string containing a concise, human-readable description of this
- * method. The format of the string is:
- *
- * <ol>
- * <li>modifiers (if any)
- * <li>return type or 'void'
- * <li>declaring class name
- * <li>'('
- * <li>parameter types, separated by ',' (if any)
- * <li>')'
- * <li>'throws' plus exception types, separated by ',' (if any)
- * </ol>
- *
- * For example: {@code public native Object
- * java.lang.Method.invoke(Object,Object) throws
- * IllegalAccessException,IllegalArgumentException
- * ,InvocationTargetException}
- *
- * @return a printable representation for this method
- */
- @Override
- public String toString() {
- StringBuilder result = new StringBuilder(Modifier.toString(getModifiers()));
-
- if (result.length() != 0)
- result.append(' ');
- result.append(returnType.getName());
- result.append(' ');
- result.append(declaringClass.getName());
- result.append('.');
- result.append(name);
- result.append("(");
- result.append(toString(parameterTypes));
- result.append(")");
- if (exceptionTypes != null && exceptionTypes.length != 0) {
- result.append(" throws ");
- result.append(toString(exceptionTypes));
- }
-
- return result.toString();
- }
-
- /**
- * Returns the constructor's signature in non-printable form. This is called
- * (only) from IO native code and needed for deriving the serialVersionUID
- * of the class
- *
- * @return The constructor's signature.
- */
- @SuppressWarnings("unused")
- private String getSignature() {
- StringBuilder result = new StringBuilder();
-
- result.append('(');
- for (int i = 0; i < parameterTypes.length; i++) {
- result.append(getSignature(parameterTypes[i]));
- }
- result.append(')');
- result.append(getSignature(returnType));
-
- return result.toString();
- }
-
-}
diff --git a/libdvm/src/main/java/java/lang/reflect/Proxy.java b/libdvm/src/main/java/java/lang/reflect/Proxy.java
deleted file mode 100644
index 3b10887..0000000
--- a/libdvm/src/main/java/java/lang/reflect/Proxy.java
+++ /dev/null
@@ -1,278 +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.lang.reflect;
-
-import java.io.Serializable;
-import java.lang.ref.WeakReference;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.WeakHashMap;
-
-/**
- * {@code Proxy} defines methods for creating dynamic proxy classes and instances.
- * A proxy class implements a declared set of interfaces and delegates method
- * invocations to an {@code InvocationHandler}.
- *
- * @see InvocationHandler
- * @since 1.3
- */
-public class Proxy implements Serializable {
-
- private static final long serialVersionUID = -2222568056686623797L;
-
- // maps class loaders to created classes by interface names
- private static final Map<ClassLoader, Map<String, WeakReference<Class<?>>>> loaderCache = new WeakHashMap<ClassLoader, Map<String, WeakReference<Class<?>>>>();
-
- // to find previously created types
- private static final Map<Class<?>, String> proxyCache = new WeakHashMap<Class<?>, String>();
-
- private static int NextClassNameIndex = 0;
-
- /**
- * The invocation handler on which the method calls are dispatched.
- */
- protected InvocationHandler h;
-
- @SuppressWarnings("unused")
- private Proxy() {
- }
-
- /**
- * Constructs a new {@code Proxy} instance with the specified invocation
- * handler.
- *
- * @param h
- * the invocation handler for the newly created proxy
- */
- protected Proxy(InvocationHandler h) {
- this.h = h;
- }
-
- /**
- * Returns the dynamically built {@code Class} for the specified interfaces.
- * Creates a new {@code Class} when necessary. The order of the interfaces
- * is relevant. Invocations of this method with the same interfaces but
- * different order result in different generated classes. The interfaces
- * must be visible from the supplied class loader; no duplicates are
- * permitted. All non-public interfaces must be defined in the same package.
- *
- * @param loader
- * the class loader that will define the proxy class
- * @param interfaces
- * an array of {@code Class} objects, each one identifying an
- * interface that will be implemented by the returned proxy
- * class
- * @return a proxy class that implements all of the interfaces referred to
- * in the contents of {@code interfaces}
- * @throws IllegalArgumentException
- * if any of the interface restrictions are violated
- * @throws NullPointerException
- * if either {@code interfaces} or any of its elements are
- * {@code null}
- */
- public static Class<?> getProxyClass(ClassLoader loader,
- Class<?>... interfaces) throws IllegalArgumentException {
- // check that interfaces are a valid array of visible interfaces
- if (interfaces == null) {
- throw new NullPointerException("interfaces == null");
- }
- String commonPackageName = null;
- for (int i = 0, length = interfaces.length; i < length; i++) {
- Class<?> next = interfaces[i];
- if (next == null) {
- throw new NullPointerException("interfaces[" + i + "] == null");
- }
- String name = next.getName();
- if (!next.isInterface()) {
- throw new IllegalArgumentException(name + " is not an interface");
- }
- if (loader != next.getClassLoader()) {
- try {
- if (next != Class.forName(name, false, loader)) {
- throw new IllegalArgumentException(name +
- " is not visible from class loader");
- }
- } catch (ClassNotFoundException ex) {
- throw new IllegalArgumentException(name + " is not visible from class loader");
- }
- }
- for (int j = i + 1; j < length; j++) {
- if (next == interfaces[j]) {
- throw new IllegalArgumentException(name + " appears more than once");
- }
- }
- if (!Modifier.isPublic(next.getModifiers())) {
- int last = name.lastIndexOf('.');
- String p = last == -1 ? "" : name.substring(0, last);
- if (commonPackageName == null) {
- commonPackageName = p;
- } else if (!commonPackageName.equals(p)) {
- throw new IllegalArgumentException("non-public interfaces must be " +
- "in the same package");
- }
- }
- }
-
- // search cache for matching proxy class using the class loader
- synchronized (loaderCache) {
- Map<String, WeakReference<Class<?>>> interfaceCache = loaderCache
- .get(loader);
- if (interfaceCache == null) {
- loaderCache
- .put(
- loader,
- (interfaceCache = new HashMap<String, WeakReference<Class<?>>>()));
- }
-
- String interfaceKey = "";
- if (interfaces.length == 1) {
- interfaceKey = interfaces[0].getName();
- } else {
- StringBuilder names = new StringBuilder();
- for (int i = 0, length = interfaces.length; i < length; i++) {
- names.append(interfaces[i].getName());
- names.append(' ');
- }
- interfaceKey = names.toString();
- }
-
- Class<?> newClass;
- WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
- if (ref == null) {
- String nextClassName = "$Proxy" + NextClassNameIndex++;
- if (commonPackageName != null && commonPackageName.length() > 0) {
- nextClassName = commonPackageName + "." + nextClassName;
- }
- if (loader == null) {
- loader = ClassLoader.getSystemClassLoader();
- }
- newClass = generateProxy(nextClassName.replace('.', '/'), interfaces, loader);
- // Need a weak reference to the class so it can
- // be unloaded if the class loader is discarded
- interfaceCache.put(interfaceKey, new WeakReference<Class<?>>(newClass));
- synchronized (proxyCache) {
- // the value is unused
- proxyCache.put(newClass, "");
- }
- } else {
- newClass = ref.get();
- assert newClass != null : "\ninterfaceKey=\"" + interfaceKey + "\""
- + "\nloaderCache=\"" + loaderCache + "\""
- + "\nintfCache=\"" + interfaceCache + "\""
- + "\nproxyCache=\"" + proxyCache + "\"";
- }
- return newClass;
- }
- }
-
- /**
- * Returns an instance of the dynamically built class for the specified
- * interfaces. Method invocations on the returned instance are forwarded to
- * the specified invocation handler. The interfaces must be visible from the
- * supplied class loader; no duplicates are permitted. All non-public
- * interfaces must be defined in the same package.
- *
- * @param loader
- * the class loader that will define the proxy class
- * @param interfaces
- * an array of {@code Class} objects, each one identifying an
- * interface that will be implemented by the returned proxy
- * object
- * @param h
- * the invocation handler that handles the dispatched method
- * invocations
- * @return a new proxy object that delegates to the handler {@code h}
- * @throws IllegalArgumentException
- * if any of the interface restrictions are violated
- * @throws NullPointerException
- * if the interfaces or any of its elements are null
- */
- public static Object newProxyInstance(ClassLoader loader,
- Class<?>[] interfaces, InvocationHandler h)
- throws IllegalArgumentException {
- if (h == null) {
- throw new NullPointerException("h == null");
- }
- try {
- return getProxyClass(loader, interfaces).getConstructor(
- new Class<?>[] { InvocationHandler.class }).newInstance(
- new Object[] { h });
- } catch (NoSuchMethodException ex) {
- throw (InternalError) (new InternalError(ex.toString())
- .initCause(ex));
- } catch (IllegalAccessException ex) {
- throw (InternalError) (new InternalError(ex.toString())
- .initCause(ex));
- } catch (InstantiationException ex) {
- throw (InternalError) (new InternalError(ex.toString())
- .initCause(ex));
- } catch (InvocationTargetException ex) {
- Throwable target = ex.getTargetException();
- throw (InternalError) (new InternalError(target.toString())
- .initCause(target));
- }
- }
-
- /**
- * Indicates whether or not the specified class is a dynamically generated
- * proxy class.
- *
- * @param cl
- * the class
- * @return {@code true} if the class is a proxy class, {@code false}
- * otherwise
- * @throws NullPointerException
- * if the class is {@code null}
- */
- public static boolean isProxyClass(Class<?> cl) {
- if (cl == null) {
- throw new NullPointerException("cl == null");
- }
- synchronized (proxyCache) {
- return proxyCache.containsKey(cl);
- }
- }
-
- /**
- * Returns the invocation handler of the specified proxy instance.
- *
- * @param proxy
- * the proxy instance
- * @return the invocation handler of the specified proxy instance
- * @throws IllegalArgumentException
- * if the supplied {@code proxy} is not a proxy object
- */
- public static InvocationHandler getInvocationHandler(Object proxy)
- throws IllegalArgumentException {
-
- if (isProxyClass(proxy.getClass())) {
- return ((Proxy) proxy).h;
- }
-
- throw new IllegalArgumentException("not a proxy instance");
- }
-
- native private static Class generateProxy(String name, Class[] interfaces,
- ClassLoader loader);
-
- /*
- * The VM clones this method's descriptor when generating a proxy class.
- * There is no implementation.
- */
- native private static void constructorPrototype(InvocationHandler h);
-}
diff --git a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java b/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
deleted file mode 100644
index 01d0e30..0000000
--- a/libdvm/src/main/java/org/apache/harmony/kernel/vm/StringUtils.java
+++ /dev/null
@@ -1,63 +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.kernel.vm;
-
-/**
- * String utility functions.
- */
-public final class StringUtils {
- /**
- * This class is uninstantiable.
- */
- private StringUtils() {
- // This space intentionally left blank.
- }
-
- /**
- * Combine a list of strings in an <code>Object[]</code> into a single
- * string.
- *
- * @param list non-null; the strings to combine
- * @return non-null; the combined form
- */
- public static String combineStrings(Object[] list) {
- int listLength = list.length;
-
- switch (listLength) {
- case 0: {
- return "";
- }
- case 1: {
- return (String) list[0];
- }
- }
-
- int strLength = 0;
-
- for (int i = 0; i < listLength; i++) {
- strLength += ((String) list[i]).length();
- }
-
- StringBuilder sb = new StringBuilder(strLength);
-
- for (int i = 0; i < listLength; i++) {
- sb.append(list[i]);
- }
-
- return sb.toString();
- }
-}
diff --git a/libdvm/src/main/java/sun/misc/Unsafe.java b/libdvm/src/main/java/sun/misc/Unsafe.java
deleted file mode 100644
index 884340b..0000000
--- a/libdvm/src/main/java/sun/misc/Unsafe.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sun.misc;
-
-import dalvik.system.VMStack;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-
-/**
- * The package name notwithstanding, this class is the quasi-standard
- * way for Java code to gain access to and use functionality which,
- * when unsupervised, would allow one to break the pointer/type safety
- * of Java.
- */
-public final class Unsafe {
- /** Traditional dalvik name. */
- private static final Unsafe THE_ONE = new Unsafe();
- /** Traditional RI name. */
- private static final Unsafe theUnsafe = THE_ONE;
-
- /**
- * This class is only privately instantiable.
- */
- private Unsafe() {}
-
- /**
- * Gets the unique instance of this class. This is only allowed in
- * very limited situations.
- */
- public static Unsafe getUnsafe() {
- /*
- * Only code on the bootclasspath is allowed to get at the
- * Unsafe instance.
- */
- ClassLoader calling = VMStack.getCallingClassLoader();
- if ((calling != null) && (calling != Unsafe.class.getClassLoader())) {
- throw new SecurityException("Unsafe access denied");
- }
-
- return THE_ONE;
- }
-
- /**
- * Gets the raw byte offset from the start of an object's memory to
- * the memory used to store the indicated instance field.
- *
- * @param field non-null; the field in question, which must be an
- * instance field
- * @return the offset to the field
- */
- public long objectFieldOffset(Field field) {
- if (Modifier.isStatic(field.getModifiers())) {
- throw new IllegalArgumentException(
- "valid for instance fields only");
- }
-
- return objectFieldOffset0(field);
- }
-
- /**
- * Helper for {@link #objectFieldOffset}, which does all the work,
- * assuming the parameter is deemed valid.
- *
- * @param field non-null; the instance field
- * @return the offset to the field
- */
- private static native long objectFieldOffset0(Field field);
-
- /**
- * Gets the offset from the start of an array object's memory to
- * the memory used to store its initial (zeroeth) element.
- *
- * @param clazz non-null; class in question; must be an array class
- * @return the offset to the initial element
- */
- public int arrayBaseOffset(Class clazz) {
- if (! clazz.isArray()) {
- throw new IllegalArgumentException(
- "valid for array classes only");
- }
-
- return arrayBaseOffset0(clazz);
- }
-
- /**
- * Helper for {@link #arrayBaseOffset}, which does all the work,
- * assuming the parameter is deemed valid.
- *
- * @return the offset to the field
- */
- private static native int arrayBaseOffset0(Class clazz);
-
- /**
- * Gets the size of each element of the given array class.
- *
- * @param clazz non-null; class in question; must be an array class
- * @return > 0; the size of each element of the array
- */
- public int arrayIndexScale(Class clazz) {
- if (! clazz.isArray()) {
- throw new IllegalArgumentException(
- "valid for array classes only");
- }
-
- return arrayIndexScale0(clazz);
- }
-
- /**
- * Helper for {@link #arrayIndexScale}, which does all the work,
- * assuming the parameter is deemed valid.
- *
- * @return the offset to the field
- */
- private static native int arrayIndexScale0(Class clazz);
-
- /**
- * Performs a compare-and-set operation on an <code>int</code>
- * field within the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param expectedValue expected value of the field
- * @param newValue new value to store in the field if the contents are
- * as expected
- * @return <code>true</code> if the new value was in fact stored, and
- * <code>false</code> if not
- */
- public native boolean compareAndSwapInt(Object obj, long offset,
- int expectedValue, int newValue);
-
- /**
- * Performs a compare-and-set operation on a <code>long</code>
- * field within the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param expectedValue expected value of the field
- * @param newValue new value to store in the field if the contents are
- * as expected
- * @return <code>true</code> if the new value was in fact stored, and
- * <code>false</code> if not
- */
- public native boolean compareAndSwapLong(Object obj, long offset,
- long expectedValue, long newValue);
-
- /**
- * Performs a compare-and-set operation on an <code>Object</code>
- * field (that is, a reference field) within the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param expectedValue expected value of the field
- * @param newValue new value to store in the field if the contents are
- * as expected
- * @return <code>true</code> if the new value was in fact stored, and
- * <code>false</code> if not
- */
- public native boolean compareAndSwapObject(Object obj, long offset,
- Object expectedValue, Object newValue);
-
- /**
- * Gets an <code>int</code> field from the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native int getIntVolatile(Object obj, long offset);
-
- /**
- * Stores an <code>int</code> field into the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putIntVolatile(Object obj, long offset, int newValue);
-
- /**
- * Gets a <code>long</code> field from the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native long getLongVolatile(Object obj, long offset);
-
- /**
- * Stores a <code>long</code> field into the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putLongVolatile(Object obj, long offset, long newValue);
-
- /**
- * Gets an <code>Object</code> field from the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native Object getObjectVolatile(Object obj, long offset);
-
- /**
- * Stores an <code>Object</code> field into the given object,
- * using <code>volatile</code> semantics.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putObjectVolatile(Object obj, long offset,
- Object newValue);
-
- /**
- * Gets an <code>int</code> field from the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native int getInt(Object obj, long offset);
-
- /**
- * Stores an <code>int</code> field into the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putInt(Object obj, long offset, int newValue);
-
- /**
- * Lazy set an int field.
- */
- public native void putOrderedInt(Object obj, long offset, int newValue);
-
- /**
- * Gets a <code>long</code> field from the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native long getLong(Object obj, long offset);
-
- /**
- * Stores a <code>long</code> field into the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putLong(Object obj, long offset, long newValue);
-
- /**
- * Lazy set a long field.
- */
- public native void putOrderedLong(Object obj, long offset, long newValue);
-
- /**
- * Gets an <code>Object</code> field from the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @return the retrieved value
- */
- public native Object getObject(Object obj, long offset);
-
- /**
- * Stores an <code>Object</code> field into the given object.
- *
- * @param obj non-null; object containing the field
- * @param offset offset to the field within <code>obj</code>
- * @param newValue the value to store
- */
- public native void putObject(Object obj, long offset, Object newValue);
-
- /**
- * Lazy set an object field.
- */
- public native void putOrderedObject(Object obj, long offset,
- Object newValue);
-
- /**
- * Parks the calling thread for the specified amount of time,
- * unless the "permit" for the thread is already available (due to
- * a previous call to {@link #unpark}. This method may also return
- * spuriously (that is, without the thread being told to unpark
- * and without the indicated amount of time elapsing).
- *
- * <p>See {@link java.util.concurrent.locks.LockSupport} for more
- * in-depth information of the behavior of this method.</p>
- *
- * @param absolute whether the given time value is absolute
- * milliseconds-since-the-epoch (<code>true</code>) or relative
- * nanoseconds-from-now (<code>false</code>)
- * @param time the (absolute millis or relative nanos) time value
- */
- public void park(boolean absolute, long time) {
- if (absolute) {
- Thread.currentThread().parkUntil(time);
- } else {
- Thread.currentThread().parkFor(time);
- }
- }
-
- /**
- * Unparks the given object, which must be a {@link Thread}.
- *
- * <p>See {@link java.util.concurrent.locks.LockSupport} for more
- * in-depth information of the behavior of this method.</p>
- *
- * @param obj non-null; the object to unpark
- */
- public void unpark(Object obj) {
- if (obj instanceof Thread) {
- ((Thread) obj).unpark();
- } else {
- throw new IllegalArgumentException("valid for Threads only");
- }
- }
-
- /**
- * Allocates an instance of the given class without running the constructor.
- * The class' <clinit> will be run, if necessary.
- */
- public native Object allocateInstance(Class<?> c);
-}
diff --git a/luni/src/main/java/java/lang/CaseMapper.java b/luni/src/main/java/java/lang/CaseMapper.java
index 4e411d1..1da621c 100644
--- a/luni/src/main/java/java/lang/CaseMapper.java
+++ b/luni/src/main/java/java/lang/CaseMapper.java
@@ -49,7 +49,7 @@
// Note that Greek isn't a particularly hard case for toLowerCase, only toUpperCase.
String languageCode = locale.getLanguage();
if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
- return ICU.toLowerCase(s, locale.toString());
+ return ICU.toLowerCase(s, locale);
}
char[] newValue = null;
@@ -59,7 +59,7 @@
char newCh;
if (ch == LATIN_CAPITAL_I_WITH_DOT || Character.isHighSurrogate(ch)) {
// Punt these hard cases.
- return ICU.toLowerCase(s, locale.toString());
+ return ICU.toLowerCase(s, locale);
} else if (ch == GREEK_CAPITAL_SIGMA && isFinalSigma(value, offset, count, i)) {
newCh = GREEK_SMALL_FINAL_SIGMA;
} else {
@@ -150,7 +150,7 @@
public static String toUpperCase(Locale locale, String s, char[] value, int offset, int count) {
String languageCode = locale.getLanguage();
if (languageCode.equals("tr") || languageCode.equals("az") || languageCode.equals("lt")) {
- return ICU.toUpperCase(s, locale.toString());
+ return ICU.toUpperCase(s, locale);
}
if (languageCode.equals("el")) {
return EL_UPPER.get().transliterate(s);
@@ -161,7 +161,7 @@
for (int o = offset, end = offset + count; o < end; o++) {
char ch = value[o];
if (Character.isHighSurrogate(ch)) {
- return ICU.toUpperCase(s, locale.toString());
+ return ICU.toUpperCase(s, locale);
}
int index = upperIndex(ch);
if (index == -1) {
diff --git a/luni/src/main/java/java/security/Signature.java b/luni/src/main/java/java/security/Signature.java
index 7dd7d93..a39d59b 100644
--- a/luni/src/main/java/java/security/Signature.java
+++ b/luni/src/main/java/java/security/Signature.java
@@ -703,7 +703,7 @@
@Override
public Object clone() throws CloneNotSupportedException {
- SignatureSpi spi = (SignatureSpi) spiImpl.clone();
+ SignatureSpi spi = spiImpl != null ? (SignatureSpi) spiImpl.clone() : null;
return new SignatureImpl(getAlgorithm(), getProvider(), spi);
}
diff --git a/luni/src/main/java/java/text/BreakIterator.java b/luni/src/main/java/java/text/BreakIterator.java
index b14647c..81545b2 100644
--- a/luni/src/main/java/java/text/BreakIterator.java
+++ b/luni/src/main/java/java/text/BreakIterator.java
@@ -268,13 +268,9 @@
/**
* Returns a new instance of {@code BreakIterator} to iterate over
* characters using the given locale.
- *
- * @param where
- * the given locale.
- * @return a new instance of {@code BreakIterator} using the given locale.
*/
- public static BreakIterator getCharacterInstance(Locale where) {
- return new RuleBasedBreakIterator(NativeBreakIterator.getCharacterInstance(where));
+ public static BreakIterator getCharacterInstance(Locale locale) {
+ return new RuleBasedBreakIterator(NativeBreakIterator.getCharacterInstance(locale));
}
/**
@@ -290,14 +286,9 @@
/**
* Returns a new instance of {@code BreakIterator} to iterate over
* line breaks using the given locale.
- *
- * @param where
- * the given locale.
- * @return a new instance of {@code BreakIterator} using the given locale.
- * @throws NullPointerException if {@code where} is {@code null}.
*/
- public static BreakIterator getLineInstance(Locale where) {
- return new RuleBasedBreakIterator(NativeBreakIterator.getLineInstance(where));
+ public static BreakIterator getLineInstance(Locale locale) {
+ return new RuleBasedBreakIterator(NativeBreakIterator.getLineInstance(locale));
}
/**
@@ -313,14 +304,9 @@
/**
* Returns a new instance of {@code BreakIterator} to iterate over
* sentence-breaks using the given locale.
- *
- * @param where
- * the given locale.
- * @return a new instance of {@code BreakIterator} using the given locale.
- * @throws NullPointerException if {@code where} is {@code null}.
*/
- public static BreakIterator getSentenceInstance(Locale where) {
- return new RuleBasedBreakIterator(NativeBreakIterator.getSentenceInstance(where));
+ public static BreakIterator getSentenceInstance(Locale locale) {
+ return new RuleBasedBreakIterator(NativeBreakIterator.getSentenceInstance(locale));
}
/**
@@ -336,14 +322,9 @@
/**
* Returns a new instance of {@code BreakIterator} to iterate over
* word-breaks using the given locale.
- *
- * @param where
- * the given locale.
- * @return a new instance of {@code BreakIterator} using the given locale.
- * @throws NullPointerException if {@code where} is {@code null}.
*/
- public static BreakIterator getWordInstance(Locale where) {
- return new RuleBasedBreakIterator(NativeBreakIterator.getWordInstance(where));
+ public static BreakIterator getWordInstance(Locale locale) {
+ return new RuleBasedBreakIterator(NativeBreakIterator.getWordInstance(locale));
}
/**
diff --git a/luni/src/main/java/java/util/Currency.java b/luni/src/main/java/java/util/Currency.java
index e8ecdde..a535bc7 100644
--- a/luni/src/main/java/java/util/Currency.java
+++ b/luni/src/main/java/java/util/Currency.java
@@ -35,7 +35,7 @@
private Currency(String currencyCode) {
this.currencyCode = currencyCode;
- String symbol = ICU.getCurrencySymbol(Locale.US.toString(), currencyCode);
+ String symbol = ICU.getCurrencySymbol(Locale.US, currencyCode);
if (symbol == null) {
throw new IllegalArgumentException("Unsupported ISO 4217 currency code: " +
currencyCode);
@@ -123,7 +123,7 @@
* @since 1.7
*/
public String getDisplayName(Locale locale) {
- return ICU.getCurrencyDisplayName(locale.toString(), currencyCode);
+ return ICU.getCurrencyDisplayName(locale, currencyCode);
}
/**
@@ -168,7 +168,7 @@
}
// Try ICU, and fall back to the currency code if ICU has nothing.
- String symbol = ICU.getCurrencySymbol(locale.toString(), currencyCode);
+ String symbol = ICU.getCurrencySymbol(locale, currencyCode);
return symbol != null ? symbol : currencyCode;
}
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index 5f24138..a3eaf21 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -782,7 +782,8 @@
/**
* Returns a locale for a given BCP-47 language tag. This method is more
* lenient than {@link Builder#setLanguageTag}. For a given language tag, parsing
- * will proceed upto the first malformed subtag. All subsequent tags are discarded.
+ * will proceed up to the first malformed subtag. All subsequent tags are discarded.
+ * Note that language tags use {@code -} rather than {@code _}, for example {@code en-US}.
*
* @throws NullPointerException if {@code languageTag} is {@code null}.
*
@@ -891,17 +892,14 @@
if (hasValidatedFields) {
Set<String> attribsCopy = new TreeSet<String>(unicodeAttributes);
- Map<String, String> keywordsCopy = new TreeMap<String, String>(
- unicodeKeywords);
- Map<Character, String> extensionsCopy = new TreeMap<Character, String>(
- extensions);
+ Map<String, String> keywordsCopy = new TreeMap<String, String>(unicodeKeywords);
+ Map<Character, String> extensionsCopy = new TreeMap<Character, String>(extensions);
// We need to transform the list of attributes & keywords set on the
// builder to a unicode locale extension. i.e, if we have any keywords
// or attributes set, Locale#getExtension('u') should return a well
// formed extension.
- addUnicodeExtensionToExtensionsMap(attribsCopy, keywordsCopy,
- extensionsCopy);
+ addUnicodeExtensionToExtensionsMap(attribsCopy, keywordsCopy, extensionsCopy);
this.unicodeAttributes = Collections.unmodifiableSet(attribsCopy);
this.unicodeKeywords = Collections.unmodifiableMap(keywordsCopy);
@@ -1006,10 +1004,16 @@
if (countryCode.isEmpty()) {
return "";
}
- String result = ICU.getDisplayCountryNative(getIcuLocaleId(), locale.getIcuLocaleId());
+
+ try {
+ Builder.normalizeAndValidateRegion(countryCode);
+ } catch (IllformedLocaleException ex) {
+ return countryCode;
+ }
+
+ String result = ICU.getDisplayCountry(this, locale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
- result = ICU.getDisplayCountryNative(getIcuLocaleId(),
- Locale.getDefault().getIcuLocaleId());
+ result = ICU.getDisplayCountry(this, Locale.getDefault());
}
return result;
}
@@ -1030,19 +1034,24 @@
return "";
}
- // http://b/8049507 --- frameworks/base should use fil_PH instead of tl_PH.
- // Until then, we're stuck covering their tracks, making it look like they're
- // using "fil" when they're not.
- String localeString = toString();
- if (languageCode.equals("tl")) {
- localeString = toNewString("fil", countryCode, variantCode, scriptCode,
- extensions);
+ // Hacks for backward compatibility.
+ //
+ // Our language tag will contain "und" if the languageCode is invalid
+ // or missing. ICU will then return "langue indéterminée" or the equivalent
+ // display language for the indeterminate language code.
+ //
+ // Sigh... ugh... and what not.
+ try {
+ Builder.normalizeAndValidateLanguage(languageCode);
+ } catch (IllformedLocaleException ex) {
+ return languageCode;
}
- String result = ICU.getDisplayLanguageNative(localeString, locale.getIcuLocaleId());
+ // TODO: We need a new hack or a complete fix for http://b/8049507 --- We would
+ // cover the frameworks' tracks when they were using "tl" instead of "fil".
+ String result = ICU.getDisplayLanguage(this, locale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
- result = ICU.getDisplayLanguageNative(localeString,
- Locale.getDefault().getIcuLocaleId());
+ result = ICU.getDisplayLanguage(this, Locale.getDefault());
}
return result;
}
@@ -1127,13 +1136,27 @@
* returned.
*/
public String getDisplayVariant(Locale locale) {
- if (variantCode.length() == 0) {
+ if (variantCode.isEmpty()) {
+ return "";
+ }
+
+ try {
+ Builder.normalizeAndValidateVariant(variantCode);
+ } catch (IllformedLocaleException ilfe) {
return variantCode;
}
- String result = ICU.getDisplayVariantNative(getIcuLocaleId(), locale.getIcuLocaleId());
+
+ String result = ICU.getDisplayVariant(this, locale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
- result = ICU.getDisplayVariantNative(getIcuLocaleId(),
- Locale.getDefault().getIcuLocaleId());
+ result = ICU.getDisplayVariant(this, Locale.getDefault());
+ }
+
+ // The "old style" locale constructors allow us to pass in variants that aren't
+ // valid BCP-47 variant subtags. When that happens, toLanguageTag will not emit
+ // them. Note that we know variantCode.length() > 0 due to the isEmpty check at
+ // the beginning of this function.
+ if (result.isEmpty()) {
+ return variantCode;
}
return result;
}
@@ -1144,7 +1167,10 @@
* @throws MissingResourceException if there's no 3-letter country code for this locale.
*/
public String getISO3Country() {
- String code = ICU.getISO3CountryNative(getIcuLocaleId());
+ // The results of getISO3Country do not depend on the languageCode,
+ // so we pass an arbitrarily selected language code here. This guards
+ // against errors caused by malformed or invalid language codes.
+ String code = ICU.getISO3Country("en-" + countryCode);
if (!countryCode.isEmpty() && code.isEmpty()) {
throw new MissingResourceException("No 3-letter country code for locale: " + this, "FormatData_" + this, "ShortCountry");
}
@@ -1157,7 +1183,16 @@
* @throws MissingResourceException if there's no 3-letter language code for this locale.
*/
public String getISO3Language() {
- String code = ICU.getISO3LanguageNative(getIcuLocaleId());
+ // For backward compatibility, we must return "" for an empty language
+ // code and not "und" which is the accurate ISO-639-3 code for an
+ // undetermined language.
+ if (languageCode.isEmpty()) {
+ return "";
+ }
+
+ // The results of getISO3Language do not depend on the country code
+ // or any of the other locale fields, so we pass just the language here.
+ String code = ICU.getISO3Language(languageCode);
if (!languageCode.isEmpty() && code.isEmpty()) {
throw new MissingResourceException("No 3-letter language code for locale: " + this, "FormatData_" + this, "ShortLanguage");
}
@@ -1233,10 +1268,9 @@
return "";
}
- String result = ICU.getDisplayScriptNative(getIcuLocaleId(), locale.getIcuLocaleId());
+ String result = ICU.getDisplayScript(this, locale);
if (result == null) { // TODO: do we need to do this, or does ICU do it for us?
- result = ICU.getDisplayScriptNative(getIcuLocaleId(),
- Locale.getDefault().getIcuLocaleId());
+ result = ICU.getDisplayScript(this, Locale.getDefault());
}
return result;
@@ -1257,7 +1291,7 @@
* where they will appear after a subtag whose value is {@code "lvariant"}.
*
* It's also important to note that the BCP-47 tag is well formed in the sense
- * that it is unambiguously parsable into its specified components. We do not
+ * that it is unambiguously parseable into its specified components. We do not
* require that any of the components are registered with the applicable registries.
* For example, we do not require scripts to be a registered ISO 15924 scripts or
* languages to appear in the ISO-639-2 code list.
@@ -1558,8 +1592,9 @@
if (locale == null) {
throw new NullPointerException("locale == null");
}
+ String languageTag = locale.toLanguageTag();
defaultLocale = locale;
- ICU.setDefaultLocale(ICU.localeIdFromLocale(locale));
+ ICU.setDefaultLocale(languageTag);
}
/**
@@ -1577,20 +1612,12 @@
public final String toString() {
String result = cachedToStringResult;
if (result == null) {
- result = cachedToStringResult = toNewString(languageCode, countryCode,
- variantCode, scriptCode, extensions);
+ result = cachedToStringResult = toNewString(languageCode, countryCode, variantCode,
+ scriptCode, extensions);
}
return result;
}
- private String getIcuLocaleId() {
- if (cachedIcuLocaleId == null) {
- cachedIcuLocaleId = ICU.localeIdFromLocale(this);
- }
-
- return cachedIcuLocaleId;
- }
-
private static String toNewString(String languageCode, String countryCode,
String variantCode, String scriptCode, Map<Character, String> extensions) {
// The string form of a locale that only has a variant is the empty string.
@@ -1605,8 +1632,7 @@
StringBuilder result = new StringBuilder(11);
result.append(languageCode);
- final boolean hasScriptOrExtensions = !scriptCode.isEmpty() ||
- !extensions.isEmpty();
+ final boolean hasScriptOrExtensions = !scriptCode.isEmpty() || !extensions.isEmpty();
if (!countryCode.isEmpty() || !variantCode.isEmpty() || hasScriptOrExtensions) {
result.append('_');
@@ -1812,8 +1838,7 @@
return true;
}
- private static boolean isValidBcp47Alpha(String string,
- int lowerBound, int upperBound) {
+ private static boolean isValidBcp47Alpha(String string, int lowerBound, int upperBound) {
final int length = string.length();
if (length < lowerBound || length > upperBound) {
return false;
diff --git a/luni/src/main/java/libcore/icu/ICU.java b/luni/src/main/java/libcore/icu/ICU.java
index cf04ff9..5978a5b 100644
--- a/luni/src/main/java/libcore/icu/ICU.java
+++ b/luni/src/main/java/libcore/icu/ICU.java
@@ -239,70 +239,6 @@
true /* has validated fields */);
}
- /**
- * Builds an ICU locale ID from the given locale. The format is very
- * straightforward. It is a series of subtags in BCP 47 order
- * {@code lang[_script][_country][_variant]} followed by the keyword
- * separator {@code @} followed by a list of keywords. Each keyword is
- * a key value pair, and appear in the form {@code k1=v1;k2=v2;...}.
- *
- * In this use case, each key is an extension identifier, and each value
- * is the value of the extension.
- */
- public static String localeIdFromLocale(Locale l) {
- StringBuilder b = new StringBuilder(16);
- b.append(l.getLanguage());
-
- final boolean hasScript = !l.getScript().isEmpty();
- final boolean hasCountry = !l.getCountry().isEmpty();
- final boolean hasVariant = !l.getVariant().isEmpty();
-
- if (hasScript || hasCountry || hasVariant) {
- b.append('_');
- if (hasScript) {
- b.append(l.getScript());
- if (hasCountry || hasVariant) {
- b.append('_');
- }
- }
-
- if (hasCountry) {
- b.append(l.getCountry());
- if (hasVariant) {
- b.append('_');
- }
- }
-
- b.append(l.getVariant());
- }
-
- if (!l.getExtensionKeys().isEmpty()) {
- b.append('@');
- // The private use extension ('x') must show up last in the list
- // so we cache its value here and append it right at the end.
- String privateUseExtensionValue = null;
- for (char c : l.getExtensionKeys()) {
- if (c == Locale.PRIVATE_USE_EXTENSION) {
- privateUseExtensionValue = l.getExtension(Locale.PRIVATE_USE_EXTENSION);
- } else {
- b.append(c);
- b.append('=');
- b.append(l.getExtension(c));
- b.append(';');
- }
- }
-
- if (privateUseExtensionValue != null) {
- b.append(Locale.PRIVATE_USE_EXTENSION);
- b.append('=');
- b.append(privateUseExtensionValue);
- b.append(';');
- }
- }
-
- return b.toString();
- }
-
public static Locale[] localesFromStrings(String[] localeNames) {
// We need to remove duplicates caused by the conversion of "he" to "iw", et cetera.
// Java needs the obsolete code, ICU needs the modern code, but we let ICU know about
@@ -349,19 +285,20 @@
return localesFromStrings(getAvailableNumberFormatLocalesNative());
}
- public static String getBestDateTimePattern(String skeleton, String localeName) {
- String key = skeleton + "\t" + localeName;
+ public static String getBestDateTimePattern(String skeleton, Locale locale) {
+ String languageTag = locale.toLanguageTag();
+ String key = skeleton + "\t" + languageTag;
synchronized (CACHED_PATTERNS) {
String pattern = CACHED_PATTERNS.get(key);
if (pattern == null) {
- pattern = getBestDateTimePatternNative(skeleton, localeName);
+ pattern = getBestDateTimePatternNative(skeleton, languageTag);
CACHED_PATTERNS.put(key, pattern);
}
return pattern;
}
}
- private static native String getBestDateTimePatternNative(String skeleton, String localeName);
+ private static native String getBestDateTimePatternNative(String skeleton, String languageTag);
public static char[] getDateFormatOrder(String pattern) {
char[] result = new char[3];
@@ -421,8 +358,17 @@
// --- Case mapping.
- public static native String toLowerCase(String s, String localeName);
- public static native String toUpperCase(String s, String localeName);
+ public static String toLowerCase(String s, Locale locale) {
+ return toLowerCase(s, locale.toLanguageTag());
+ }
+
+ private static native String toLowerCase(String s, String languageTag);
+
+ public static String toUpperCase(String s, Locale locale) {
+ return toUpperCase(s, locale.toLanguageTag());
+ }
+
+ private static native String toUpperCase(String s, String languageTag);
// --- Errors.
@@ -448,18 +394,49 @@
public static native String[] getAvailableCurrencyCodes();
public static native String getCurrencyCode(String countryCode);
- public static native String getCurrencyDisplayName(String locale, String currencyCode);
+
+ public static String getCurrencyDisplayName(Locale locale, String currencyCode) {
+ return getCurrencyDisplayName(locale.toLanguageTag(), currencyCode);
+ }
+
+ private static native String getCurrencyDisplayName(String languageTag, String currencyCode);
+
public static native int getCurrencyFractionDigits(String currencyCode);
public static native int getCurrencyNumericCode(String currencyCode);
- public static native String getCurrencySymbol(String locale, String currencyCode);
- public static native String getDisplayCountryNative(String countryCode, String locale);
- public static native String getDisplayLanguageNative(String languageCode, String locale);
- public static native String getDisplayVariantNative(String variantCode, String locale);
- public static native String getDisplayScriptNative(String variantCode, String locale);
+ public static String getCurrencySymbol(Locale locale, String currencyCode) {
+ return getCurrencySymbol(locale.toLanguageTag(), currencyCode);
+ }
- public static native String getISO3CountryNative(String locale);
- public static native String getISO3LanguageNative(String locale);
+ private static native String getCurrencySymbol(String languageTag, String currencyCode);
+
+ public static String getDisplayCountry(Locale targetLocale, Locale locale) {
+ return getDisplayCountryNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+ }
+
+ private static native String getDisplayCountryNative(String targetLanguageTag, String languageTag);
+
+ public static String getDisplayLanguage(Locale targetLocale, Locale locale) {
+ return getDisplayLanguageNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+ }
+
+ private static native String getDisplayLanguageNative(String targetLanguageTag, String languageTag);
+
+ public static String getDisplayVariant(Locale targetLocale, Locale locale) {
+ return getDisplayVariantNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+ }
+
+ private static native String getDisplayVariantNative(String targetLanguageTag, String languageTag);
+
+ public static String getDisplayScript(Locale targetLocale, Locale locale) {
+ return getDisplayScriptNative(targetLocale.toLanguageTag(), locale.toLanguageTag());
+ }
+
+ private static native String getDisplayScriptNative(String targetLanguageTag, String languageTag);
+
+ public static native String getISO3Country(String languageTag);
+
+ public static native String getISO3Language(String languageTag);
public static native String addLikelySubtags(String locale);
public static native String getScript(String locale);
@@ -471,6 +448,6 @@
static native boolean initLocaleDataNative(String locale, LocaleData result);
- public static native void setDefaultLocale(String locale);
+ public static native void setDefaultLocale(String languageTag);
public static native String getDefaultLocale();
}
diff --git a/luni/src/main/java/libcore/icu/LocaleData.java b/luni/src/main/java/libcore/icu/LocaleData.java
index 49228b3..845ba32 100644
--- a/luni/src/main/java/libcore/icu/LocaleData.java
+++ b/luni/src/main/java/libcore/icu/LocaleData.java
@@ -176,8 +176,8 @@
}
// Get the "h:mm a" and "HH:mm" 12- and 24-hour time format strings.
- localeData.timeFormat12 = ICU.getBestDateTimePattern("hm", locale.toString());
- localeData.timeFormat24 = ICU.getBestDateTimePattern("Hm", locale.toString());
+ localeData.timeFormat12 = ICU.getBestDateTimePattern("hm", locale);
+ localeData.timeFormat24 = ICU.getBestDateTimePattern("Hm", locale);
// Fix up a couple of patterns.
if (localeData.fullTimeFormat != null) {
diff --git a/luni/src/main/java/libcore/icu/NativeBreakIterator.java b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
index 7168d96..992aac2 100644
--- a/luni/src/main/java/libcore/icu/NativeBreakIterator.java
+++ b/luni/src/main/java/libcore/icu/NativeBreakIterator.java
@@ -138,23 +138,23 @@
}
public int preceding(int offset) {
- return precedingImpl(this.address, this.string, offset);
+ return precedingImpl(this.address, this.string, offset);
}
- public static NativeBreakIterator getCharacterInstance(Locale where) {
- return new NativeBreakIterator(getCharacterInstanceImpl(where.toString()), BI_CHAR_INSTANCE);
+ public static NativeBreakIterator getCharacterInstance(Locale locale) {
+ return new NativeBreakIterator(getCharacterInstanceImpl(locale.toLanguageTag()), BI_CHAR_INSTANCE);
}
- public static NativeBreakIterator getLineInstance(Locale where) {
- return new NativeBreakIterator(getLineInstanceImpl(where.toString()), BI_LINE_INSTANCE);
+ public static NativeBreakIterator getLineInstance(Locale locale) {
+ return new NativeBreakIterator(getLineInstanceImpl(locale.toLanguageTag()), BI_LINE_INSTANCE);
}
- public static NativeBreakIterator getSentenceInstance(Locale where) {
- return new NativeBreakIterator(getSentenceInstanceImpl(where.toString()), BI_SENT_INSTANCE);
+ public static NativeBreakIterator getSentenceInstance(Locale locale) {
+ return new NativeBreakIterator(getSentenceInstanceImpl(locale.toLanguageTag()), BI_SENT_INSTANCE);
}
- public static NativeBreakIterator getWordInstance(Locale where) {
- return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
+ public static NativeBreakIterator getWordInstance(Locale locale) {
+ return new NativeBreakIterator(getWordInstanceImpl(locale.toLanguageTag()), BI_WORD_INSTANCE);
}
private static native long getCharacterInstanceImpl(String locale);
diff --git a/luni/src/main/java/libcore/icu/NativeCollation.java b/luni/src/main/java/libcore/icu/NativeCollation.java
index 64e0278..b4b4f46 100644
--- a/luni/src/main/java/libcore/icu/NativeCollation.java
+++ b/luni/src/main/java/libcore/icu/NativeCollation.java
@@ -10,6 +10,8 @@
package libcore.icu;
+import java.util.Locale;
+
/**
* Package static class for declaring all native methods for collation use.
* @author syn wee quek
@@ -26,7 +28,10 @@
public static native long 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 long openCollator(Locale locale) {
+ return openCollator(locale.toLanguageTag());
+ }
+ private static native long openCollator(String languageTag);
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);
diff --git a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
index 3ea942d..b23013b 100644
--- a/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
+++ b/luni/src/main/java/libcore/icu/RuleBasedCollatorICU.java
@@ -52,7 +52,7 @@
}
public RuleBasedCollatorICU(Locale locale) {
- address = NativeCollation.openCollator(locale.toString());
+ address = NativeCollation.openCollator(locale);
}
private RuleBasedCollatorICU(long address) {
diff --git a/luni/src/main/native/IcuUtilities.cpp b/luni/src/main/native/IcuUtilities.cpp
index c6f3950..7ce2168 100644
--- a/luni/src/main/native/IcuUtilities.cpp
+++ b/luni/src/main/native/IcuUtilities.cpp
@@ -28,10 +28,6 @@
#include "unicode/uloc.h"
#include "unicode/ustring.h"
-Locale getLocale(JNIEnv* env, jstring localeName) {
- return Locale::createFromName(ScopedUtfChars(env, localeName).c_str());
-}
-
jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration* se) {
if (maybeThrowIcuException(env, provider, status)) {
return NULL;
diff --git a/luni/src/main/native/IcuUtilities.h b/luni/src/main/native/IcuUtilities.h
index ffcfcda..737379e 100644
--- a/luni/src/main/native/IcuUtilities.h
+++ b/luni/src/main/native/IcuUtilities.h
@@ -23,9 +23,7 @@
#include "jni.h"
#include "ustrenum.h" // For UStringEnumeration.
#include "unicode/utypes.h" // For UErrorCode.
-#include "unicode/locid.h" // For Locale.
-extern Locale getLocale(JNIEnv* env, jstring localeName);
extern jobjectArray fromStringEnumeration(JNIEnv* env, UErrorCode& status, const char* provider, StringEnumeration*);
bool maybeThrowIcuException(JNIEnv* env, const char* function, UErrorCode error);
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index 13a0b1c..87ebc21 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -254,7 +254,7 @@
#if defined(IFA_F_TEMPORARY)
initConstant(env, c, "IFA_F_TEMPORARY", IFA_F_TEMPORARY);
#endif
-#if defined(IDA_F_TENTATIVE)
+#if defined(IFA_F_TENTATIVE)
initConstant(env, c, "IFA_F_TENTATIVE", IFA_F_TENTATIVE);
#endif
initConstant(env, c, "IFF_ALLMULTI", IFF_ALLMULTI);
@@ -390,19 +390,15 @@
initConstant(env, c, "PROT_READ", PROT_READ);
initConstant(env, c, "PROT_WRITE", PROT_WRITE);
initConstant(env, c, "R_OK", R_OK);
-#if defined(RT_SCOPE_HOST)
+// NOTE: The RT_* constants are not preprocessor defines, they're enum
+// members. The best we can do (barring UAPI / kernel version checks) is
+// to hope they exist on all host linuxes we're building on. These
+// constants have been around since 2.6.35 at least, so we should be ok.
+#if !defined(__APPLE__)
initConstant(env, c, "RT_SCOPE_HOST", RT_SCOPE_HOST);
-#endif
-#if defined(RT_SCOPE_LINK)
initConstant(env, c, "RT_SCOPE_LINK", RT_SCOPE_LINK);
-#endif
-#if defined(RT_SCOPE_NOWHERE)
initConstant(env, c, "RT_SCOPE_NOWHERE", RT_SCOPE_NOWHERE);
-#endif
-#if defined(RT_SCOPE_SITE)
initConstant(env, c, "RT_SCOPE_SITE", RT_SCOPE_SITE);
-#endif
-#if defined(RT_SCOPE_UNIVERSE)
initConstant(env, c, "RT_SCOPE_UNIVERSE", RT_SCOPE_UNIVERSE);
#endif
initConstant(env, c, "SEEK_CUR", SEEK_CUR);
diff --git a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
index bb05193..e0638bd 100644
--- a/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
+++ b/luni/src/main/native/libcore_icu_AlphabeticIndex.cpp
@@ -20,6 +20,7 @@
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
+#include "ScopedIcuLocale.h"
#include "ScopedJavaUnicodeString.h"
#include "unicode/alphaindex.h"
#include "unicode/uniset.h"
@@ -28,9 +29,13 @@
return reinterpret_cast<AlphabeticIndex*>(static_cast<uintptr_t>(peer));
}
-static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong AlphabeticIndex_create(JNIEnv* env, jclass, jstring javaLocaleName) {
UErrorCode status = U_ZERO_ERROR;
- AlphabeticIndex* ai = new AlphabeticIndex(getLocale(env, javaLocale), status);
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return 0;
+ }
+ AlphabeticIndex* ai = new AlphabeticIndex(icuLocale.locale(), status);
if (maybeThrowIcuException(env, "AlphabeticIndex", status)) {
return 0;
}
@@ -53,10 +58,14 @@
maybeThrowIcuException(env, "AlphabeticIndex::setMaxLabelCount", status);
}
-static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocale) {
+static void AlphabeticIndex_addLabels(JNIEnv* env, jclass, jlong peer, jstring javaLocaleName) {
AlphabeticIndex* ai = fromPeer(peer);
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return;
+ }
UErrorCode status = U_ZERO_ERROR;
- ai->addLabels(getLocale(env, javaLocale), status);
+ ai->addLabels(icuLocale.locale(), status);
maybeThrowIcuException(env, "AlphabeticIndex::addLabels", status);
}
diff --git a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
index 72bc631..a3258c1 100644
--- a/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
+++ b/luni/src/main/native/libcore_icu_DateIntervalFormat.cpp
@@ -18,13 +18,17 @@
#include "IcuUtilities.h"
#include "JniConstants.h"
+#include "ScopedIcuLocale.h"
#include "ScopedJavaUnicodeString.h"
#include "UniquePtr.h"
#include "cutils/log.h"
#include "unicode/dtitvfmt.h"
static jlong DateIntervalFormat_createDateIntervalFormat(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName, jstring javaTzName) {
- Locale locale = getLocale(env, javaLocaleName);
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return 0;
+ }
ScopedJavaUnicodeString skeletonHolder(env, javaSkeleton);
if (!skeletonHolder.valid()) {
@@ -32,7 +36,7 @@
}
UErrorCode status = U_ZERO_ERROR;
- DateIntervalFormat* formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), locale, status));
+ DateIntervalFormat* formatter(DateIntervalFormat::createInstance(skeletonHolder.unicodeString(), icuLocale.locale(), status));
if (maybeThrowIcuException(env, "DateIntervalFormat::createInstance", status)) {
return 0;
}
diff --git a/luni/src/main/native/libcore_icu_ICU.cpp b/luni/src/main/native/libcore_icu_ICU.cpp
index 7b1aac1..163d19c 100644
--- a/luni/src/main/native/libcore_icu_ICU.cpp
+++ b/luni/src/main/native/libcore_icu_ICU.cpp
@@ -21,6 +21,7 @@
#include "JniConstants.h"
#include "JniException.h"
#include "ScopedFd.h"
+#include "ScopedIcuLocale.h"
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
@@ -96,30 +97,30 @@
DISALLOW_COPY_AND_ASSIGN(ScopedResourceBundle);
};
-static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocale) {
+static jstring ICU_addLikelySubtags(JNIEnv* env, jclass, jstring javaLocaleName) {
UErrorCode status = U_ZERO_ERROR;
- ScopedUtfChars localeID(env, javaLocale);
+ ScopedUtfChars localeID(env, javaLocaleName);
char maximizedLocaleID[ULOC_FULLNAME_CAPACITY];
uloc_addLikelySubtags(localeID.c_str(), maximizedLocaleID, sizeof(maximizedLocaleID), &status);
if (U_FAILURE(status)) {
- return javaLocale;
+ return javaLocaleName;
}
return env->NewStringUTF(maximizedLocaleID);
}
-static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocale) {
- UErrorCode status = U_ZERO_ERROR;
- ScopedUtfChars localeID(env, javaLocale);
- char script[ULOC_SCRIPT_CAPACITY];
- uloc_getScript(localeID.c_str(), script, sizeof(script), &status);
- if (U_FAILURE(status)) {
- return NULL;
- }
- return env->NewStringUTF(script);
+static jstring ICU_getScript(JNIEnv* env, jclass, jstring javaLocaleName) {
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ return env->NewStringUTF(icuLocale.locale().getScript());
}
static jstring ICU_localeForLanguageTag(JNIEnv* env, jclass, jstring languageTag, jboolean strict) {
ScopedUtfChars languageTagChars(env, languageTag);
+ if (languageTagChars.c_str() == NULL) {
+ return NULL;
+ }
// Naively assume that in the average case, the size of
// the normalized language tag will be very nearly the same as the
@@ -158,8 +159,7 @@
// NOTE: The cast is safe because parsedLength can never be negative thanks
// to the check above. ICU does not document any negative return values for
// that field, but check for it anyway.
- if ((strict == JNI_TRUE) &&
- (static_cast<uint32_t>(parsedLength) != languageTagChars.size())) {
+ if ((strict == JNI_TRUE) && (static_cast<uint32_t>(parsedLength) != languageTagChars.size())) {
return NULL;
}
@@ -228,9 +228,9 @@
return (charCount == 0) ? env->NewStringUTF("XXX") : env->NewString(chars, charCount);
}
-static jstring getCurrencyName(JNIEnv* env, jstring javaLocaleName, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
- ScopedUtfChars localeName(env, javaLocaleName);
- if (localeName.c_str() == NULL) {
+static jstring getCurrencyName(JNIEnv* env, jstring javaLanguageTag, jstring javaCurrencyCode, UCurrNameStyle nameStyle) {
+ ScopedUtfChars languageTag(env, javaLanguageTag);
+ if (languageTag.c_str() == NULL) {
return NULL;
}
ScopedJavaUnicodeString currencyCode(env, javaCurrencyCode);
@@ -241,7 +241,7 @@
UErrorCode status = U_ZERO_ERROR;
UBool isChoiceFormat = false;
int32_t charCount;
- const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), localeName.c_str(),
+ const UChar* chars = ucurr_getName(icuCurrencyCode.getTerminatedBuffer(), languageTag.c_str(),
nameStyle, &isChoiceFormat, &charCount, &status);
if (status == U_USING_DEFAULT_WARNING) {
if (nameStyle == UCURR_SYMBOL_NAME) {
@@ -260,54 +260,88 @@
return (charCount == 0) ? NULL : env->NewString(chars, charCount);
}
-static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaCurrencyCode) {
- return getCurrencyName(env, javaLocaleName, javaCurrencyCode, UCURR_LONG_NAME);
+static jstring ICU_getCurrencyDisplayName(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
+ return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_LONG_NAME);
}
-static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaCurrencyCode) {
- return getCurrencyName(env, javaLocaleName, javaCurrencyCode, UCURR_SYMBOL_NAME);
+static jstring ICU_getCurrencySymbol(JNIEnv* env, jclass, jstring javaLanguageTag, jstring javaCurrencyCode) {
+ return getCurrencyName(env, javaLanguageTag, javaCurrencyCode, UCURR_SYMBOL_NAME);
}
-static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
- Locale loc = getLocale(env, locale);
- Locale targetLoc = getLocale(env, targetLocale);
- UnicodeString str;
- targetLoc.getDisplayCountry(loc, str);
- return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayCountryNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+ if (!icuTargetLocale.valid()) {
+ return NULL;
+ }
+
+ UnicodeString str;
+ icuTargetLocale.locale().getDisplayCountry(icuLocale.locale(), str);
+ return env->NewString(str.getBuffer(), str.length());
}
-static jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
- Locale loc = getLocale(env, locale);
- Locale targetLoc = getLocale(env, targetLocale);
- UnicodeString str;
- targetLoc.getDisplayLanguage(loc, str);
- return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayLanguageNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+ if (!icuTargetLocale.valid()) {
+ return NULL;
+ }
+
+ UnicodeString str;
+ icuTargetLocale.locale().getDisplayLanguage(icuLocale.locale(), str);
+ return env->NewString(str.getBuffer(), str.length());
}
-static jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
- Locale loc = getLocale(env, locale);
- Locale targetLoc = getLocale(env, targetLocale);
- UnicodeString str;
- targetLoc.getDisplayScript(loc, str);
- return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayScriptNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+ if (!icuTargetLocale.valid()) {
+ return NULL;
+ }
+
+ UnicodeString str;
+ icuTargetLocale.locale().getDisplayScript(icuLocale.locale(), str);
+ return env->NewString(str.getBuffer(), str.length());
}
-static jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring targetLocale, jstring locale) {
- Locale loc = getLocale(env, locale);
- Locale targetLoc = getLocale(env, targetLocale);
- UnicodeString str;
- targetLoc.getDisplayVariant(loc, str);
- return env->NewString(str.getBuffer(), str.length());
+static jstring ICU_getDisplayVariantNative(JNIEnv* env, jclass, jstring javaTargetLanguageTag, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ ScopedIcuLocale icuTargetLocale(env, javaTargetLanguageTag);
+ if (!icuTargetLocale.valid()) {
+ return NULL;
+ }
+
+ UnicodeString str;
+ icuTargetLocale.locale().getDisplayVariant(icuLocale.locale(), str);
+ return env->NewString(str.getBuffer(), str.length());
}
-static jstring ICU_getISO3CountryNative(JNIEnv* env, jclass, jstring locale) {
- Locale loc = getLocale(env, locale);
- return env->NewStringUTF(loc.getISO3Country());
+static jstring ICU_getISO3Country(JNIEnv* env, jclass, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ return env->NewStringUTF(icuLocale.locale().getISO3Country());
}
-static jstring ICU_getISO3LanguageNative(JNIEnv* env, jclass, jstring locale) {
- Locale loc = getLocale(env, locale);
- return env->NewStringUTF(loc.getISO3Language());
+static jstring ICU_getISO3Language(JNIEnv* env, jclass, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+ return env->NewStringUTF(icuLocale.locale().getISO3Language());
}
static jobjectArray ICU_getISOCountriesNative(JNIEnv* env, jclass) {
@@ -538,7 +572,10 @@
return JNI_FALSE; // ICU has a fixed-length limit.
}
- Locale locale = getLocale(env, javaLocaleName);
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return JNI_FALSE;
+ }
// Get the DateTimePatterns.
UErrorCode status = U_ZERO_ERROR;
@@ -557,7 +594,7 @@
// Get the "Yesterday", "Today", and "Tomorrow" strings.
bool foundYesterdayTodayAndTomorrow = false;
for (LocaleNameIterator it(localeName.c_str(), status); it.HasNext(); it.Up()) {
- if (getYesterdayTodayAndTomorrow(env, localeData, locale, it.Get())) {
+ if (getYesterdayTodayAndTomorrow(env, localeData, icuLocale.locale(), it.Get())) {
foundYesterdayTodayAndTomorrow = true;
break;
}
@@ -568,7 +605,7 @@
}
status = U_ZERO_ERROR;
- UniquePtr<Calendar> cal(Calendar::createInstance(locale, status));
+ UniquePtr<Calendar> cal(Calendar::createInstance(icuLocale.locale(), status));
if (U_FAILURE(status)) {
return JNI_FALSE;
}
@@ -578,7 +615,7 @@
// Get DateFormatSymbols.
status = U_ZERO_ERROR;
- DateFormatSymbols dateFormatSym(locale, status);
+ DateFormatSymbols dateFormatSym(icuLocale.locale(), status);
if (U_FAILURE(status)) {
return JNI_FALSE;
}
@@ -631,8 +668,8 @@
status = U_ZERO_ERROR;
// For numberPatterns and symbols.
- setNumberPatterns(env, localeData, locale);
- setDecimalFormatSymbolsData(env, localeData, locale);
+ setNumberPatterns(env, localeData, icuLocale.locale());
+ setDecimalFormatSymbolsData(env, localeData, icuLocale.locale());
jstring countryCode = env->NewStringUTF(Locale::createFromName(localeName.c_str()).getCountry());
jstring internationalCurrencySymbol = ICU_getCurrencyCode(env, NULL, countryCode);
@@ -655,25 +692,33 @@
return JNI_TRUE;
}
-static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
+static jstring ICU_toLowerCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) {
ScopedJavaUnicodeString scopedString(env, javaString);
if (!scopedString.valid()) {
return NULL;
}
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
UnicodeString& s(scopedString.unicodeString());
UnicodeString original(s);
- s.toLower(getLocale(env, localeName));
+ s.toLower(icuLocale.locale());
return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
-static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring localeName) {
+static jstring ICU_toUpperCase(JNIEnv* env, jclass, jstring javaString, jstring javaLanguageTag) {
ScopedJavaUnicodeString scopedString(env, javaString);
if (!scopedString.valid()) {
return NULL;
}
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
UnicodeString& s(scopedString.unicodeString());
UnicodeString original(s);
- s.toUpper(getLocale(env, localeName));
+ s.toUpper(icuLocale.locale());
return s == original ? javaString : env->NewString(s.getBuffer(), s.length());
}
@@ -708,10 +753,14 @@
return fromStringEnumeration(env, status, "ucurr_openISOCurrencies", &e);
}
-static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLocaleName) {
- Locale locale = getLocale(env, javaLocaleName);
+static jstring ICU_getBestDateTimePatternNative(JNIEnv* env, jclass, jstring javaSkeleton, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
+
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(locale, status));
+ UniquePtr<DateTimePatternGenerator> generator(DateTimePatternGenerator::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "DateTimePatternGenerator::createInstance", status)) {
return NULL;
}
@@ -728,16 +777,14 @@
return env->NewString(result.getBuffer(), result.length());
}
-static void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLocaleName) {
- Locale locale = getLocale(env, javaLocaleName);
- UErrorCode status = U_ZERO_ERROR;
+static void ICU_setDefaultLocale(JNIEnv* env, jclass, jstring javaLanguageTag) {
+ ScopedIcuLocale icuLocale(env, javaLanguageTag);
+ if (!icuLocale.valid()) {
+ return;
+ }
- // TODO: Should we check whether locale.isBogus() here ? ICU will
- // accept bogus locales as the default without complaint. It
- // shouldn't make a difference in practice, users that set a bogus
- // locale as the default shouldn't have any realistic expectation that
- // things like defaults etc. will work correctly.
- Locale::setDefault(locale, status);
+ UErrorCode status = U_ZERO_ERROR;
+ Locale::setDefault(icuLocale.locale(), status);
maybeThrowIcuException(env, "Locale::setDefault", status);
}
@@ -766,8 +813,8 @@
NATIVE_METHOD(ICU, getDisplayLanguageNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getDisplayScriptNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getDisplayVariantNative, "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(ICU, getISO3CountryNative, "(Ljava/lang/String;)Ljava/lang/String;"),
- NATIVE_METHOD(ICU, getISO3LanguageNative, "(Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(ICU, getISO3Country, "(Ljava/lang/String;)Ljava/lang/String;"),
+ NATIVE_METHOD(ICU, getISO3Language, "(Ljava/lang/String;)Ljava/lang/String;"),
NATIVE_METHOD(ICU, getISOCountriesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getISOLanguagesNative, "()[Ljava/lang/String;"),
NATIVE_METHOD(ICU, getIcuVersion, "()Ljava/lang/String;"),
diff --git a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
index 0c8c3c9..ef0c2a9 100644
--- a/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
+++ b/luni/src/main/native/libcore_icu_NativeBreakIterator.cpp
@@ -20,6 +20,7 @@
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
+#include "ScopedIcuLocale.h"
#include "ScopedUtfChars.h"
#include "unicode/brkiter.h"
#include "unicode/putil.h"
@@ -107,13 +108,12 @@
};
#define MAKE_BREAK_ITERATOR_INSTANCE(F) \
- UErrorCode status = U_ZERO_ERROR; \
- const ScopedUtfChars localeChars(env, javaLocale); \
- if (localeChars.c_str() == NULL) { \
+ ScopedIcuLocale icuLocale(env, javaLocaleName); \
+ if (!icuLocale.valid()) { \
return 0; \
} \
- Locale locale(Locale::createFromName(localeChars.c_str())); \
- BreakIterator* it = F(locale, status); \
+ UErrorCode status = U_ZERO_ERROR; \
+ BreakIterator* it = F(icuLocale.locale(), status); \
if (maybeThrowIcuException(env, "ubrk_open", status)) { \
return 0; \
} \
@@ -143,19 +143,19 @@
return it->following(offset);
}
-static jlong NativeBreakIterator_getCharacterInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getCharacterInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createCharacterInstance);
}
-static jlong NativeBreakIterator_getLineInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getLineInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createLineInstance);
}
-static jlong NativeBreakIterator_getSentenceInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getSentenceInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createSentenceInstance);
}
-static jlong NativeBreakIterator_getWordInstanceImpl(JNIEnv* env, jclass, jstring javaLocale) {
+static jlong NativeBreakIterator_getWordInstanceImpl(JNIEnv* env, jclass, jstring javaLocaleName) {
MAKE_BREAK_ITERATOR_INSTANCE(BreakIterator::createWordInstance);
}
diff --git a/luni/src/main/native/libcore_icu_NativeCollation.cpp b/luni/src/main/native/libcore_icu_NativeCollation.cpp
index 00ec9ae..4ce42ec 100644
--- a/luni/src/main/native/libcore_icu_NativeCollation.cpp
+++ b/luni/src/main/native/libcore_icu_NativeCollation.cpp
@@ -180,11 +180,12 @@
return result;
}
-static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring localeName) {
- ScopedUtfChars localeChars(env, localeName);
+static jlong NativeCollation_openCollator(JNIEnv* env, jclass, jstring javaLocaleName) {
+ ScopedUtfChars localeChars(env, javaLocaleName);
if (localeChars.c_str() == NULL) {
return 0;
}
+
UErrorCode status = U_ZERO_ERROR;
UCollator* c = ucol_open(localeChars.c_str(), &status);
maybeThrowIcuException(env, "ucol_open", status);
diff --git a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
index ef1743e..faf87f1 100644
--- a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
@@ -20,6 +20,7 @@
#include "JNIHelp.h"
#include "JniConstants.h"
#include "JniException.h"
+#include "ScopedIcuLocale.h"
#include "ScopedJavaUnicodeString.h"
#include "ScopedLocalRef.h"
#include "ScopedUtfChars.h"
@@ -59,11 +60,14 @@
return true;
}
-static void TimeZoneNames_fillZoneStrings(JNIEnv* env, jclass, jstring localeName, jobjectArray result) {
- Locale locale = getLocale(env, localeName);
+static void TimeZoneNames_fillZoneStrings(JNIEnv* env, jclass, jstring javaLocaleName, jobjectArray result) {
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return;
+ }
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(locale, status));
+ UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
return;
}
@@ -118,11 +122,14 @@
}
}
-static jstring TimeZoneNames_getExemplarLocation(JNIEnv* env, jclass, jstring javaLocale, jstring javaTz) {
- Locale locale = getLocale(env, javaLocale);
+static jstring TimeZoneNames_getExemplarLocation(JNIEnv* env, jclass, jstring javaLocaleName, jstring javaTz) {
+ ScopedIcuLocale icuLocale(env, javaLocaleName);
+ if (!icuLocale.valid()) {
+ return NULL;
+ }
UErrorCode status = U_ZERO_ERROR;
- UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(locale, status));
+ UniquePtr<TimeZoneNames> names(TimeZoneNames::createInstance(icuLocale.locale(), status));
if (maybeThrowIcuException(env, "TimeZoneNames::createInstance", status)) {
return NULL;
}
diff --git a/luni/src/test/java/libcore/android/system/OsConstantsTest.java b/luni/src/test/java/libcore/android/system/OsConstantsTest.java
new file mode 100644
index 0000000..681d68c
--- /dev/null
+++ b/luni/src/test/java/libcore/android/system/OsConstantsTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 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 android.system;
+
+import junit.framework.TestCase;
+
+public class OsConstantsTest extends TestCase {
+
+ // http://b/15602893
+ public void testBug15602893() {
+ assertTrue(OsConstants.RT_SCOPE_HOST > 0);
+ assertTrue(OsConstants.RT_SCOPE_LINK > 0);
+ assertTrue(OsConstants.RT_SCOPE_SITE > 0);
+
+ assertTrue(OsConstants.IFA_F_TENTATIVE > 0);
+ }
+}
diff --git a/luni/src/test/java/libcore/icu/ICUTest.java b/luni/src/test/java/libcore/icu/ICUTest.java
index 60ed0ca..be2da25 100644
--- a/luni/src/test/java/libcore/icu/ICUTest.java
+++ b/luni/src/test/java/libcore/icu/ICUTest.java
@@ -16,6 +16,8 @@
package libcore.icu;
+import java.text.BreakIterator;
+import java.text.Collator;
import java.util.Arrays;
import java.util.Locale;
@@ -42,12 +44,12 @@
}
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"));
+ assertEquals("d MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("ca", "ES")));
+ assertEquals("d 'de' MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("es", "ES")));
+ assertEquals("d. MMMM", ICU.getBestDateTimePattern("MMMMd", new Locale("de", "CH")));
+ assertEquals("MMMM d", ICU.getBestDateTimePattern("MMMMd", new Locale("en", "US")));
+ assertEquals("d LLLL", ICU.getBestDateTimePattern("MMMMd", new Locale("fa", "IR")));
+ assertEquals("M月d日", ICU.getBestDateTimePattern("MMMMd", new Locale("ja", "JP")));
}
public void test_localeFromString() throws Exception {
@@ -73,7 +75,7 @@
}
private String best(Locale l, String skeleton) {
- return ICU.getBestDateTimePattern(skeleton, l.toString());
+ return ICU.getBestDateTimePattern(skeleton, l);
}
public void test_getDateFormatOrder() throws Exception {
@@ -123,4 +125,95 @@
} catch (IllegalArgumentException expected) {
}
}
+
+ public void testScriptsPassedToIcu() throws Exception {
+ Locale sr_Cyrl_BA = Locale.forLanguageTag("sr-Cyrl-BA");
+ Locale sr_Cyrl_ME = Locale.forLanguageTag("sr-Cyrl-ME");
+ Locale sr_Latn_BA = Locale.forLanguageTag("sr-Latn-BA");
+ Locale sr_Latn_ME = Locale.forLanguageTag("sr-Latn-ME");
+
+ assertEquals("sr_BA_#Cyrl", sr_Cyrl_BA.toString());
+ assertEquals("Cyrl", sr_Cyrl_BA.getScript());
+
+ assertEquals("sr_ME_#Cyrl", sr_Cyrl_ME.toString());
+ assertEquals("Cyrl", sr_Cyrl_ME.getScript());
+
+ assertEquals("sr_BA_#Latn", sr_Latn_BA.toString());
+ assertEquals("Latn", sr_Latn_BA.getScript());
+
+ assertEquals("sr_ME_#Latn", sr_Latn_ME.toString());
+ assertEquals("Latn", sr_Latn_ME.getScript());
+
+ assertEquals("Српски", sr_Cyrl_BA.getDisplayLanguage(sr_Cyrl_BA));
+ assertEquals("Босна и Херцеговина", sr_Cyrl_BA.getDisplayCountry(sr_Cyrl_BA));
+ assertEquals("Ћирилица", sr_Cyrl_BA.getDisplayScript(sr_Cyrl_BA));
+ assertEquals("", sr_Cyrl_BA.getDisplayVariant(sr_Cyrl_BA));
+
+ assertEquals("Српски", sr_Cyrl_ME.getDisplayLanguage(sr_Cyrl_ME));
+ assertEquals("Црна Гора", sr_Cyrl_ME.getDisplayCountry(sr_Cyrl_ME));
+ assertEquals("Ћирилица", sr_Cyrl_ME.getDisplayScript(sr_Cyrl_ME));
+ assertEquals("", sr_Cyrl_ME.getDisplayVariant(sr_Cyrl_ME));
+
+ assertEquals("Srpski", sr_Latn_BA.getDisplayLanguage(sr_Latn_BA));
+ assertEquals("Bosna i Hercegovina", sr_Latn_BA.getDisplayCountry(sr_Latn_BA));
+ assertEquals("Latinica", sr_Latn_BA.getDisplayScript(sr_Latn_BA));
+ assertEquals("", sr_Latn_BA.getDisplayVariant(sr_Latn_BA));
+
+ assertEquals("Srpski", sr_Latn_ME.getDisplayLanguage(sr_Latn_ME));
+ assertEquals("Crna Gora", sr_Latn_ME.getDisplayCountry(sr_Latn_ME));
+ assertEquals("Latinica", sr_Latn_ME.getDisplayScript(sr_Latn_ME));
+ assertEquals("", sr_Latn_ME.getDisplayVariant(sr_Latn_ME));
+
+ assertEquals("BIH", sr_Cyrl_BA.getISO3Country());
+ assertEquals("srp", sr_Cyrl_BA.getISO3Language());
+ assertEquals("MNE", sr_Cyrl_ME.getISO3Country());
+ assertEquals("srp", sr_Cyrl_ME.getISO3Language());
+ assertEquals("BIH", sr_Latn_BA.getISO3Country());
+ assertEquals("srp", sr_Latn_BA.getISO3Language());
+ assertEquals("MNE", sr_Latn_ME.getISO3Country());
+ assertEquals("srp", sr_Latn_ME.getISO3Language());
+
+ BreakIterator.getCharacterInstance(sr_Cyrl_BA);
+ BreakIterator.getCharacterInstance(sr_Cyrl_ME);
+ BreakIterator.getCharacterInstance(sr_Latn_BA);
+ BreakIterator.getCharacterInstance(sr_Latn_ME);
+
+ BreakIterator.getLineInstance(sr_Cyrl_BA);
+ BreakIterator.getLineInstance(sr_Cyrl_ME);
+ BreakIterator.getLineInstance(sr_Latn_BA);
+ BreakIterator.getLineInstance(sr_Latn_ME);
+
+ BreakIterator.getSentenceInstance(sr_Cyrl_BA);
+ BreakIterator.getSentenceInstance(sr_Cyrl_ME);
+ BreakIterator.getSentenceInstance(sr_Latn_BA);
+ BreakIterator.getSentenceInstance(sr_Latn_ME);
+
+ BreakIterator.getWordInstance(sr_Cyrl_BA);
+ BreakIterator.getWordInstance(sr_Cyrl_ME);
+ BreakIterator.getWordInstance(sr_Latn_BA);
+ BreakIterator.getWordInstance(sr_Latn_ME);
+
+ Collator.getInstance(sr_Cyrl_BA);
+ Collator.getInstance(sr_Cyrl_ME);
+ Collator.getInstance(sr_Latn_BA);
+ Collator.getInstance(sr_Latn_ME);
+
+ // TODO: This needs to be fixed. We shouldn't output attribute key
+ // expansions in the language tag or the toString output. The tests
+ // will fail with something like:
+ //
+ // expected:<de-u-co[-phonebk-kf-upper-kn]> but was:
+ // <de-u-co[lcasefirst-upper-collation-phonebook-colnumeric-yes]>
+ Locale l = Locale.forLanguageTag("de-u-co-phonebk-kf-upper-kn");
+ assertEquals("de__#u-co-phonebk-kf-upper-kn", l.toString());
+ assertEquals("de-u-co-phonebk-kf-upper-kn", l.toLanguageTag());
+
+ Collator c = Collator.getInstance(l);
+ assertTrue(c.compare("2", "11") < 0);
+ assertTrue(c.compare("11", "ae") < 0);
+ assertTrue(c.compare("ae", "Ä") < 0);
+ assertTrue(c.compare("Ä", "ä") < 0);
+ assertTrue(c.compare("ä", "AF") < 0);
+ assertTrue(c.compare("AF", "af") < 0);
+ }
}
diff --git a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
index 55e088f..09a18e2 100644
--- a/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
+++ b/luni/src/test/java/libcore/java/security/KeyPairGeneratorTest.java
@@ -54,28 +54,63 @@
public class KeyPairGeneratorTest extends TestCase {
public void test_providerCount() {
- // If this fails remember to add/remove _provider methods below. This test is sharded
- // because it takes so long.
- assertEquals(4, Security.getProviders().length);
+ Provider[] providers = Security.getProviders();
+ // We expect there to be at least one provider.
+ assertTrue(providers.length > 0);
+ // If this fails remember to add _provider methods below. This test is sharded because it
+ // takes a long time to execute.
+ assertTrue(providers.length < 10);
}
public void test_getInstance_provider0() throws Exception {
- test_getInstance(Security.getProviders()[0]);
+ test_getInstance(0);
}
public void test_getInstance_provider1() throws Exception {
- test_getInstance(Security.getProviders()[1]);
+ test_getInstance(1);
}
public void test_getInstance_provider2() throws Exception {
- test_getInstance(Security.getProviders()[2]);
+ test_getInstance(2);
}
public void test_getInstance_provider3() throws Exception {
- test_getInstance(Security.getProviders()[3]);
+ test_getInstance(3);
}
- private void test_getInstance(Provider provider) throws Exception {
+ public void test_getInstance_provider4() throws Exception {
+ test_getInstance(4);
+ }
+
+ public void test_getInstance_provider5() throws Exception {
+ test_getInstance(5);
+ }
+
+ public void test_getInstance_provider6() throws Exception {
+ test_getInstance(6);
+ }
+
+ public void test_getInstance_provider7() throws Exception {
+ test_getInstance(7);
+ }
+
+ public void test_getInstance_provider8() throws Exception {
+ test_getInstance(8);
+ }
+
+ public void test_getInstance_provider9() throws Exception {
+ test_getInstance(9);
+ }
+
+ private void test_getInstance(int providerIndex) throws Exception {
+ Provider[] providers = Security.getProviders();
+ if (providerIndex >= providers.length) {
+ // Providers can be added by vendors and other tests. We do not
+ // specify a fixed number and silenty pass if the provider at the
+ // specified index does not exist.
+ return;
+ }
+ Provider provider = providers[providerIndex];
Set<Provider.Service> services = provider.getServices();
for (Provider.Service service : services) {
String type = service.getType();
diff --git a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
index c58f83a..722924d 100644
--- a/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/DecimalFormatTest.java
@@ -260,4 +260,26 @@
} catch (NullPointerException expected) {
}
}
+
+ // Confirm the fraction digits do not change when the currency is changed.
+ public void testBug71369() {
+ final String nonBreakingSpace = "\u00A0";
+
+ NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.GERMAN);
+ numberFormat.setCurrency(Currency.getInstance("USD"));
+
+ assertEquals("2,01" + nonBreakingSpace + "$", numberFormat.format(2.01));
+
+ numberFormat.setMinimumFractionDigits(0);
+ numberFormat.setMaximumFractionDigits(0);
+
+ String expected = "2" + nonBreakingSpace + "$";
+ assertEquals(expected, numberFormat.format(2.01));
+
+ // Changing the currency must not reset the digits.
+ numberFormat.setCurrency(Currency.getInstance("EUR"));
+ numberFormat.setCurrency(Currency.getInstance("USD"));
+
+ assertEquals(expected, numberFormat.format(2.01));
+ }
}
diff --git a/luni/src/test/java/libcore/java/util/LocaleTest.java b/luni/src/test/java/libcore/java/util/LocaleTest.java
index b87dc97..f3b31bb 100644
--- a/luni/src/test/java/libcore/java/util/LocaleTest.java
+++ b/luni/src/test/java/libcore/java/util/LocaleTest.java
@@ -39,9 +39,22 @@
// and variant, but a display name made up of the raw strings.
// Newer releases return slightly different results, but no less unreasonable.
assertEquals("aabbcc", invalid.getDisplayLanguage());
- assertEquals("", invalid.getDisplayCountry());
- assertEquals("DDEEFF_GGHHII", invalid.getDisplayVariant());
- assertEquals("aabbcc (DDEEFF,DDEEFF_GGHHII)", invalid.getDisplayName());
+ assertEquals("DDEEFF", invalid.getDisplayCountry());
+ assertEquals("GGHHII", invalid.getDisplayVariant());
+ assertEquals("aabbcc (DDEEFF,GGHHII)", invalid.getDisplayName());
+ }
+
+ public void test_getDisplayName_emptyCodes() {
+ Locale emptyLanguage = new Locale("", "DdeEFf");
+ assertEquals("", emptyLanguage.getDisplayLanguage());
+
+ Locale emptyCountry = new Locale("AaBbCc", "");
+ assertEquals("", emptyCountry.getDisplayCountry());
+
+ Locale emptyCountryAndLanguage = new Locale("", "", "Farl");
+ assertEquals("", emptyCountryAndLanguage.getDisplayLanguage());
+ assertEquals("", emptyCountryAndLanguage.getDisplayCountry());
+ assertEquals("Farl", emptyCountryAndLanguage.getDisplayVariant());
}
// http://b/2611311; if there's no display language/country/variant, use the raw codes.
@@ -53,8 +66,8 @@
assertEquals("xx", unknown.getDisplayLanguage());
assertEquals("YY", unknown.getDisplayCountry());
- assertEquals("TRADITIONAL", unknown.getDisplayVariant());
- assertEquals("xx (YY,TRADITIONAL)", unknown.getDisplayName());
+ assertEquals("Traditional", unknown.getDisplayVariant());
+ assertEquals("xx (YY,Traditional)", unknown.getDisplayName());
}
public void test_getDisplayName_easy() throws Exception {
@@ -173,6 +186,10 @@
assertEquals("CAN", new Locale("", "CA").getISO3Country());
assertEquals("CAN", new Locale("en", "CA").getISO3Country());
assertEquals("CAN", new Locale("xx", "CA").getISO3Country());
+
+ // 3 letter country codes.
+ assertEquals("CAN", new Locale("en", "CAN").getISO3Country());
+ assertEquals("CAN", new Locale("frankenderp", "CAN").getISO3Country());
}
public void test_getISO3Language() {
@@ -192,6 +209,10 @@
assertEquals("eng", new Locale("en", "").getISO3Language());
assertEquals("eng", new Locale("en", "CA").getISO3Language());
assertEquals("eng", new Locale("en", "XX").getISO3Language());
+
+ // 3 letter language code.
+ assertEquals("eng", new Locale("eng", "USA").getISO3Language());
+ assertEquals("eng", new Locale("eng", "US").getISO3Language());
}
public void test_Builder_setLanguage() {
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
index 7886e3e..ad084e1 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/Signature2Test.java
@@ -68,7 +68,17 @@
* java.security.Signature#clone()
*/
public void test_clone() throws Exception {
+ // A Signature may be cloneable according to the API, in practice the implementation isn't
+ // once it has been initialized. Checking for runtime exceptions rather than useful
+ // behavior.
Signature s = Signature.getInstance("DSA");
+ Signature clone = (Signature) s.clone();
+ assertNotNull(clone);
+ assertEquals(s.getAlgorithm(), clone.getAlgorithm());
+ assertEquals(s.getProvider(), clone.getProvider());
+
+ KeyPair keyPair = getDsaKeys();
+ s.initSign(keyPair.getPrivate());
try {
s.clone();
fail();