Merge "Remove conflicting package infromation for java.security packages"
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 97e94f8..5955f27 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -101,10 +101,7 @@
LOCAL_JAVA_RESOURCE_DIRS := $(core_resource_dirs)
LOCAL_NO_STANDARD_LIBRARIES := true
LOCAL_JAVACFLAGS := $(local_javac_flags)
-# TODO(oth): Remove --min-sdk-version=26 when the O SDK version is determined.
-# For now it represents the minimum sdk version required for invoke-polymorphic.
-# This is only needed when ANDROID_COMPILE_WITH_JACK=false (b/36118520).
-LOCAL_DX_FLAGS := --core-library --min-sdk-version=26
+LOCAL_DX_FLAGS := --core-library
LOCAL_MODULE_TAGS := optional
LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_MODULE := core-oj
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..72d7fb4
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,3 @@
+nfuller@google.com
+pszczepaniak@google.com
+android-libcore-team+review@google.com
diff --git a/expectations/virtualdeviceknownfailures.txt b/expectations/virtualdeviceknownfailures.txt
index 54d0d64..300bfde 100644
--- a/expectations/virtualdeviceknownfailures.txt
+++ b/expectations/virtualdeviceknownfailures.txt
@@ -12,5 +12,15 @@
description: "Virtual devices do not implement the SELinux policy (forbid hard link) asserted by this test",
name: "libcore.java.nio.file.Files2Test#test_createLink",
bug: 35670953
+},
+{
+ description: "multicast not supported in virtual device testing infra",
+ names: ["org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_InetAddress_IPv4",
+ "org.apache.harmony.tests.java.net.MulticastSocketTest#test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4_nullInterface",
+ "org.apache.harmony.tests.java.net.MulticastSocketTest#test_leaveGroupLjava_net_InetAddress_IPv4",
+ "org.apache.harmony.tests.java.net.MulticastSocketTest#test_sendLjava_net_DatagramPacketB_IPv4",
+ "org.apache.harmony.tests.java.net.MulticastSocketTest#test_setLoopbackModeSendReceive_IPv4"
+ ],
+ bug: 35922755
}
]
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index adad301..20a4a47 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -521,6 +521,9 @@
public static final int TCP_NODELAY = placeholder();
public static final int TCP_USER_TIMEOUT = placeholder();
/** @hide */ public static final int TIOCOUTQ = placeholder();
+ /** @hide */ public static final int UDP_ENCAP = placeholder();
+ /** @hide */ public static final int UDP_ENCAP_ESPINUDP_NON_IKE = placeholder();
+ /** @hide */ public static final int UDP_ENCAP_ESPINUDP = placeholder();
/** @hide */ public static final int UNIX_PATH_MAX = placeholder();
public static final int WCONTINUED = placeholder();
public static final int WEXITED = placeholder();
diff --git a/luni/src/main/java/libcore/icu/TimeZoneNames.java b/luni/src/main/java/libcore/icu/TimeZoneNames.java
index 917d9ce..68e6e30 100644
--- a/luni/src/main/java/libcore/icu/TimeZoneNames.java
+++ b/luni/src/main/java/libcore/icu/TimeZoneNames.java
@@ -43,15 +43,6 @@
public static final int NAME_COUNT = 5;
private static final ZoneStringsCache cachedZoneStrings = new ZoneStringsCache();
- static {
- // Ensure that we pull in the zone strings for the root locale, en_US, and the
- // user's default locale. (All devices must support the root locale and en_US,
- // and they're used for various system things like HTTP headers.) Pre-populating
- // the cache is especially useful on Android because we'll share this via the Zygote.
- cachedZoneStrings.get(Locale.ROOT);
- cachedZoneStrings.get(Locale.US);
- cachedZoneStrings.get(Locale.getDefault());
- }
public static class ZoneStringsCache extends BasicLruCache<Locale, String[][]> {
public ZoneStringsCache() {
@@ -71,6 +62,7 @@
fillZoneStrings(locale.toLanguageTag(), result);
long nativeEnd = System.nanoTime();
+ addOffsetStrings(result);
internStrings(result);
// Ending up in this method too often is an easy way to make your app slow, so we ensure
// it's easy to tell from the log (a) what we were doing, (b) how long it took, and
@@ -83,8 +75,33 @@
return result;
}
+ /**
+ * Generate offset strings for cases where we don't have a name. Note that this is a
+ * potentially slow operation, as we need to load the timezone data for all affected
+ * time zones.
+ */
+ private void addOffsetStrings(String[][] result) {
+ for (int i = 0; i < result.length; ++i) {
+ TimeZone tz = null;
+ for (int j = 1; j < NAME_COUNT; ++j) {
+ if (result[i][j] != null) {
+ continue;
+ }
+ if (tz == null) {
+ tz = TimeZone.getTimeZone(result[i][0]);
+ }
+ int offsetMillis = tz.getRawOffset();
+ if (j == LONG_NAME_DST || j == SHORT_NAME_DST) {
+ offsetMillis += tz.getDSTSavings();
+ }
+ result[i][j] = TimeZone.createGmtOffsetString(
+ /* includeGmt */ true, /*includeMinuteSeparator */true, offsetMillis);
+ }
+ }
+ }
+
// De-duplicate the strings (http://b/2672057).
- private synchronized void internStrings(String[][] result) {
+ private void internStrings(String[][] result) {
HashMap<String, String> internTable = new HashMap<String, String>();
for (int i = 0; i < result.length; ++i) {
for (int j = 1; j < NAME_COUNT; ++j) {
diff --git a/luni/src/main/java/libcore/net/MimeUtils.java b/luni/src/main/java/libcore/net/MimeUtils.java
index b746273..693b6da 100644
--- a/luni/src/main/java/libcore/net/MimeUtils.java
+++ b/luni/src/main/java/libcore/net/MimeUtils.java
@@ -51,8 +51,7 @@
add("application/mathematica", "nb");
add("application/msaccess", "mdb");
add("application/oda", "oda");
- add("application/ogg", "ogg");
- add("application/ogg", "oga");
+ add("application/ogg", "ogx");
add("application/pdf", "pdf");
add("application/pgp-keys", "key");
add("application/pgp-signature", "pgp");
@@ -240,6 +239,9 @@
add("audio/mpeg", "mp2");
add("audio/mpeg", "m4a");
add("audio/mpegurl", "m3u");
+ add("audio/ogg", "oga");
+ add("audio/ogg", "ogg");
+ add("audio/ogg", "spx");
add("audio/prs.sid", "sid");
add("audio/x-aiff", "aif");
add("audio/x-aiff", "aiff");
@@ -372,6 +374,7 @@
add("video/mpeg", "mpe");
add("video/mp4", "mp4");
add("video/mpeg", "VOB");
+ add("video/ogg", "ogv");
add("video/quicktime", "qt");
add("video/quicktime", "mov");
add("video/vnd.mpegurl", "mxu");
diff --git a/luni/src/main/native/android_system_OsConstants.cpp b/luni/src/main/native/android_system_OsConstants.cpp
index 3ae4af6..a517475 100644
--- a/luni/src/main/native/android_system_OsConstants.cpp
+++ b/luni/src/main/native/android_system_OsConstants.cpp
@@ -47,6 +47,9 @@
#include <linux/if_addr.h>
#include <linux/rtnetlink.h>
+// Include linux socket constants for setting sockopts
+#include <linux/udp.h>
+
#include <net/if.h> // After <sys/socket.h> to work around a Mac header file bug.
#if defined(__BIONIC__)
@@ -577,6 +580,9 @@
initConstant(env, c, "TCP_USER_TIMEOUT", TCP_USER_TIMEOUT);
#endif
initConstant(env, c, "TIOCOUTQ", TIOCOUTQ);
+ initConstant(env, c, "UDP_ENCAP", UDP_ENCAP);
+ initConstant(env, c, "UDP_ENCAP_ESPINUDP_NON_IKE", UDP_ENCAP_ESPINUDP_NON_IKE);
+ initConstant(env, c, "UDP_ENCAP_ESPINUDP", UDP_ENCAP_ESPINUDP);
// UNIX_PATH_MAX is mentioned in some versions of unix(7), but not actually declared.
initConstant(env, c, "UNIX_PATH_MAX", sizeof(sockaddr_un::sun_path));
initConstant(env, c, "WCONTINUED", WCONTINUED);
diff --git a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
index b85f69a..c199bca 100644
--- a/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
+++ b/luni/src/test/java/libcore/java/io/FileInputStreamTest.java
@@ -264,11 +264,6 @@
assertEquals(0, Libcore.os.lseek(fis.getFD(), 0, OsConstants.SEEK_CUR));
assertEquals(lastByte, fis.skip(lastByte));
}
-
- FileInputStream fis = new FileInputStream(largeFile);
- long lastByte = 3 * 1024 * 1024 * 1024L - 1;
- assertEquals(0, Libcore.os.lseek(fis.getFD(), 0, OsConstants.SEEK_CUR));
- assertEquals(lastByte, fis.skip(lastByte));
} finally {
// Proactively cleanup - it's a pretty large file.
assertTrue(largeFile.delete());
diff --git a/luni/src/test/java/libcore/java/lang/LambdaImplementationTest.java b/luni/src/test/java/libcore/java/lang/LambdaImplementationTest.java
index d32fa20..0161c6a 100644
--- a/luni/src/test/java/libcore/java/lang/LambdaImplementationTest.java
+++ b/luni/src/test/java/libcore/java/lang/LambdaImplementationTest.java
@@ -27,6 +27,7 @@
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -35,18 +36,22 @@
public class LambdaImplementationTest extends TestCase {
- private static final String MSG = "Hello World";
+ private static final String STATIC_METHOD_RESPONSE = "StaticMethodResponse";
public void testNonCapturingLambda() throws Exception {
- Callable<String> r1 = () -> MSG;
+ Callable<String> r1 = () -> "Hello World";
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaImplementsInterfaces(r1, Callable.class);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertNonSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, "Hello World");
- Callable<String> r2 = () -> MSG;
- assertMultipleInstanceCharacteristics(r1, r2);
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ callables.add(() -> "Hello World");
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
interface Condition<T> {
@@ -83,65 +88,96 @@
assertLambdaMethodCharacteristics(r1, Callable.class);
assertNonSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, STATIC_METHOD_RESPONSE);
- Callable<String> r2 = LambdaImplementationTest::staticMethod;
- assertMultipleInstanceCharacteristics(r1, r2);
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ callables.add(LambdaImplementationTest::staticMethod);
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
public void testObjectMethodReferenceLambda() throws Exception {
- StringBuilder o = new StringBuilder(MSG);
+ String msg = "Hello";
+ StringBuilder o = new StringBuilder(msg);
Callable<String> r1 = o::toString;
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaImplementsInterfaces(r1, Callable.class);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertNonSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, msg);
- Callable<String> r2 = o::toString;
- assertMultipleInstanceCharacteristics(r1, r2);
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ callables.add(o::toString);
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
public void testArgumentCapturingLambda() throws Exception {
- String msg = MSG;
+ checkArgumentCapturingLambda("Argument");
+ }
+
+ private void checkArgumentCapturingLambda(String msg) throws Exception {
Callable<String> r1 = () -> msg;
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaImplementsInterfaces(r1, Callable.class);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertNonSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, msg);
- Callable<String> r2 = () -> msg;
- assertMultipleInstanceCharacteristics(r1, r2);
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ callables.add(() -> msg);
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
public void testSerializableLambda_withoutState() throws Exception {
- Callable<String> r1 = (Callable<String> & Serializable) () -> MSG;
+ Callable<String> r1 = (Callable<String> & Serializable) () -> "No State";
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, "No State");
- Callable<String> r2 = (Callable<String> & Serializable) () -> MSG;
- assertMultipleInstanceCharacteristics(r1, r2);
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ Callable<String> callable = (Callable<String> & Serializable) () -> "No State";
+ assertLambdaImplementsInterfaces(callable, Callable.class, Serializable.class);
+ callables.add(callable);
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
public void testSerializableLambda_withState() throws Exception {
- final int state = 123;
- Callable<String> r1 = (Callable<String> & Serializable) () -> MSG + state;
+ final long state = System.currentTimeMillis();
+ Callable<String> r1 = (Callable<String> & Serializable) () -> "State:" + state;
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaImplementsInterfaces(r1, Callable.class, Serializable.class);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG + state);
+ assertCallableBehavior(r1, "State:" + state);
Callable<String> deserializedR1 = roundtripSerialization(r1);
assertEquals(r1.call(), deserializedR1.call());
+
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ Callable<String> callable = (Callable<String> & Serializable) () -> "State:" + state;
+ assertLambdaImplementsInterfaces(callable, Callable.class, Serializable.class);
+ callables.add(callable);
+ }
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
public void testBadSerializableLambda() throws Exception {
@@ -159,14 +195,25 @@
}
public void testMultipleInterfaceLambda() throws Exception {
- Callable<String> r1 = (Callable<String> & MarkerInterface) () -> MSG;
+ Callable<String> r1 = (Callable<String> & MarkerInterface) () -> "MultipleInterfaces";
assertTrue(r1 instanceof MarkerInterface);
assertGeneralLambdaClassCharacteristics(r1);
assertLambdaMethodCharacteristics(r1, Callable.class);
assertLambdaImplementsInterfaces(r1, Callable.class, MarkerInterface.class);
assertNonSerializableLambdaCharacteristics(r1);
- assertCallableBehavior(r1, MSG);
+ assertCallableBehavior(r1, "MultipleInterfaces");
+
+ List<Callable<String>> callables = new ArrayList<>();
+ for (int i = 0; i < 2; i++) {
+ Callable<String> callable =
+ (Callable<String> & MarkerInterface) () -> "MultipleInterfaces";
+ assertLambdaImplementsInterfaces(callable, Callable.class, MarkerInterface.class);
+ callables.add(callable);
+ }
+ assertLambdaImplementsInterfaces(r1, Callable.class, MarkerInterface.class);
+ assertMultipleDefinitionCharacteristics(r1, callables.get(0));
+ assertMultipleInstanceCharacteristics(callables.get(0), callables.get(1));
}
private static void assertSerializableLambdaCharacteristics(Object r1) throws Exception {
@@ -248,8 +295,15 @@
}
}
- private static void assertMultipleInstanceCharacteristics(Object r1, Object r2)
- throws Exception {
+ /**
+ * Asserts that necessary conditions hold when there are two lambdas with separate but identical
+ * definitions.
+ */
+ private static void assertMultipleDefinitionCharacteristics(
+ Callable<String> r1, Callable<String> r2) throws Exception {
+
+ // Sanity check that the lambdas do the same thing.
+ assertEquals(r1.call(), r2.call());
// Unclear if any of this is *guaranteed* to be true.
@@ -258,10 +312,23 @@
assertNotSame(r1, r2);
assertTrue(!r1.equals(r2));
- // Confirm the classes differ.
- Class<?> lambda1Class = r1.getClass();
- Class<?> lambda2Class = r2.getClass();
- assertNotSame(lambda1Class, lambda2Class);
+ // Two lambdas from different definitions can share the same class or may not.
+ // See JLS 15.27.4.
+ }
+
+ /**
+ * Asserts that necessary conditions hold when there are two lambdas created from the same
+ * definition.
+ */
+ private static void assertMultipleInstanceCharacteristics(
+ Callable<String> r1, Callable<String> r2) throws Exception {
+
+ // Sanity check that the lambdas do the same thing.
+ assertEquals(r1.call(), r2.call());
+
+ // There doesn't appear to be anything else that is safe to assert here. Two lambdas
+ // created from the same definition can be the same, as can their class, but they can also
+ // be different. See JLS 15.27.4.
}
private static void assertGeneralLambdaClassCharacteristics(Object r1) throws Exception {
@@ -333,7 +400,7 @@
}
private static String staticMethod() {
- return MSG;
+ return STATIC_METHOD_RESPONSE;
}
private interface MarkerInterface {
diff --git a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
index 9bf02ef..5866ae4 100644
--- a/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
+++ b/luni/src/test/java/libcore/java/lang/invoke/MethodHandleCombinersTest.java
@@ -1924,4 +1924,417 @@
MethodType.methodType(void.class, MethodHandle.class, String.class));
invokeMultiThreaded(MethodHandles.insertArguments(mh, 0, adapter, "a: c+d ,b:c ,c:d ,d:e"));
}
+
+ private static void checkBooleanCast_delegate(boolean expected, boolean z, boolean b,
+ boolean c, boolean s, boolean i, boolean j,
+ boolean f, boolean d, boolean l) {
+ assertEquals(expected, z);
+ assertEquals(expected, b);
+ assertEquals(expected, c);
+ assertEquals(expected, s);
+ assertEquals(expected, i);
+ assertEquals(expected, j);
+ assertEquals(expected, f);
+ assertEquals(expected, d);
+ assertEquals(expected, l);
+ }
+
+ private static void checkByteCast_delegate(byte expected, byte z, byte b, byte c, byte s,
+ byte i, byte j, byte f, byte d, byte l) {
+ int mask = 0xff;
+ assertEquals(expected & 1, z);
+ assertEquals(expected, b);
+ assertEquals(expected, c & mask);
+ assertEquals(expected, s & mask);
+ assertEquals(expected, i & mask);
+ assertEquals(expected, j & mask);
+ assertEquals(expected, f & mask);
+ assertEquals(expected, d & mask);
+ assertEquals(expected, l);
+ }
+
+ private static void checkCharCast_delegate(char expected, char z, char b, char c, char s,
+ char i, char j, char f, char d, char l) {
+ int mask = 0xffff;
+ assertEquals(expected & 1, z);
+ assertEquals(expected & 0xff, b);
+ assertEquals(expected, c);
+ assertEquals(expected, s & mask);
+ assertEquals(expected, i & mask);
+ assertEquals(expected, j & mask);
+ assertEquals(expected, f & mask);
+ assertEquals(expected, d & mask);
+ assertEquals(expected, l);
+ }
+
+ private static void checkShortCast_delegate(short expected, short z, short b, short c, short s,
+ short i, short j, short f, short d, short l) {
+ int mask = 0xffff;
+ assertEquals(expected & 1, z);
+ assertEquals(expected & 0xff, b);
+ assertEquals(expected, c & mask);
+ assertEquals(expected, s);
+ assertEquals(expected, i & mask);
+ assertEquals(expected, j & mask);
+ assertEquals(expected, f & mask);
+ assertEquals(expected, d & mask);
+ assertEquals(expected, l);
+ }
+
+ private static void checkIntCast_delegate(int expected, int z, int b, int c, int s, int i,
+ int j, int f, int d, int l) {
+ int mask = 0xffffffff;
+ assertEquals(expected & 1, z);
+ assertEquals(expected & 0xff, b);
+ assertEquals(expected & 0xffff, c);
+ assertEquals(expected & 0xffff, s);
+ assertEquals(expected, i & mask);
+ assertEquals(expected, j & mask);
+ assertEquals(expected, f & mask);
+ assertEquals(expected, d & mask);
+ assertEquals(expected, l);
+ }
+
+ private static void checkLongCast_delegate(long expected, long z, long b, long c, long s,
+ long i, long j, long f, long d, long l) {
+ long mask = 0xffffffffl;
+ assertEquals(expected & 1, z);
+ assertEquals(expected & 0xff, b);
+ assertEquals(expected & 0xffff, c);
+ assertEquals(expected & 0xffff, s);
+ assertEquals(expected & mask, i & mask);
+ assertEquals(expected, j);
+ assertEquals(expected & mask, f & mask);
+ assertEquals(expected, d);
+ assertEquals(expected, l);
+ }
+
+ private static void checkFloatCast_delegate(float expected, float z, float b, float c, float s,
+ float i, float j, float f, float d, float l) {
+ assertEquals((byte) expected & 1, (int) z);
+ assertEquals((byte) expected, (int) b & 0xff);
+ assertEquals((char) expected & 0xffff, (int) c& 0xffff);
+ assertEquals((short) expected & 0xffff, (int) s & 0xffff);
+ assertEquals((int) expected, (int) i);
+ assertEquals((long) expected, (long) j);
+ assertEquals(expected, f);
+ assertEquals(expected, d);
+ assertEquals(expected, l);
+ }
+
+ private static void checkDoubleCast_delegate(double expected, double z, double b, double c,
+ double s, double i, double j, double f, double d,
+ double l) {
+ assertEquals((byte) expected & 1, (int) z);
+ assertEquals((byte) expected & 0xff, (int) b & 0xff);
+ assertEquals((int) expected & 0xffff, (int) c & 0xffff);
+ assertEquals((int) expected & 0xffff, (int) s & 0xffff);
+ assertEquals((int) expected, (int) i);
+ assertEquals((long) expected, (long) j);
+ assertEquals((float) expected, (float) f);
+ assertEquals(expected, d);
+ assertEquals(expected, l);
+ }
+
+ private static void checkBoxingCasts_delegate(boolean expected, Boolean z, Byte b, Character c,
+ Short s, Integer i, Long j, Float f, Double d) {
+ int v = expected ? 1 : 0;
+ assertEquals(Boolean.valueOf(expected ? true : false), z);
+ assertEquals(Byte.valueOf((byte) v), b);
+ assertEquals(Character.valueOf((char) v), c);
+ assertEquals(Short.valueOf((short) v), s);
+ assertEquals(Integer.valueOf(v), i);
+ assertEquals(Long.valueOf(v), j);
+ assertEquals(Float.valueOf(v), f);
+ assertEquals(Double.valueOf(v), d);
+ }
+
+ public static void testExplicitCastArguments() throws Throwable {
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkBooleanCast_delegate",
+ MethodType.methodType(void.class, boolean.class, boolean.class, boolean.class,
+ boolean.class, boolean.class, boolean.class, boolean.class,
+ boolean.class, boolean.class, boolean.class));
+ MethodHandle mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Boolean.class));
+ mh.invokeExact(false, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0,
+ Boolean.valueOf(false));
+ mh.invokeExact(false, false, (byte) 2, (char) 2, (short) 2, 2, 2l, 2.2f, 2.2,
+ Boolean.valueOf(false));
+ mh.invokeExact(true, true, (byte) 1, (char) 1, (short) 1, 1, 1l, 1.0f, 1.0,
+ Boolean.valueOf(true));
+ mh.invokeExact(true, true, (byte) 51, (char) 51, (short) 51, 51, 51l, 51.0f, 51.0,
+ Boolean.valueOf(true));
+ MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, String.class));
+ try {
+ mh.invoke(true, true, (byte) 51, (char) 51, (short) 51, 51, 51l, 51.0f, 51.0,
+ "ClassCastException here!");
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkByteCast_delegate",
+ MethodType.methodType(void.class, byte.class, byte.class, byte.class,
+ byte.class, byte.class, byte.class, byte.class,
+ byte.class, byte.class, byte.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, byte.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Byte.class));
+ mh.invokeExact((byte) 0x5a, false, (byte) 0x5a, (char) 0x5a5a, (short) 0x5a5a, (int) 0x5a5a,
+ (long) 0x5a5a, (float) 0x5a5a, (double) 0x5a5a, Byte.valueOf((byte) 0x5a));
+ try {
+ mh.invoke((byte) 0x5a, false, (byte) 0x5a, (char) 0x5a5a, (short) 0x5a5a, (int) 0x5a5a,
+ (long) 0x5a5a, (float) 0x5a5a, (double) 0x5a5a,
+ Short.valueOf((short) 0x5a5a));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkCharCast_delegate",
+ MethodType.methodType(void.class, char.class, char.class, char.class,
+ char.class, char.class, char.class, char.class,
+ char.class, char.class, char.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, char.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Character.class));
+ mh.invokeExact((char) 0x5555, true, (byte) 0x5555, (char) 0x5555, (short) 0x5555,
+ (int) 0x5555, (long) 0x5555, (float) 0x5555, (double) 0x5555,
+ Character.valueOf((char) 0x5555));
+ try {
+ mh.invoke((char) 0x5555, false, (byte) 0x5555, (char) 0x5555, (short) 0x5555,
+ (int) 0x5555, (long) 0x5555, (float) 0x5555, (double) 0x5555,
+ Integer.valueOf((int) 0x5555));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkShortCast_delegate",
+ MethodType.methodType(void.class, short.class, short.class, short.class,
+ short.class, short.class, short.class, short.class,
+ short.class, short.class, short.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, short.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Short.class));
+ mh.invokeExact((short) 0x3773, true, (byte) 0x3773, (char) 0x3773, (short) 0x3773,
+ (int) 0x3773, (long) 0x3773, (float) 0x3773, (double) 0x3773,
+ Short.valueOf((short) 0x3773));
+ try {
+ mh.invoke((short) 0x3773, true, (byte) 0x3773, (char) 0x3773, (short) 0x3773,
+ (int) 0x3773, (long) 0x3773, (float) 0x3773, (double) 0x3773,
+ Long.valueOf((long) 0x3773));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkIntCast_delegate",
+ MethodType.methodType(void.class, int.class, int.class, int.class,
+ int.class, int.class, int.class, int.class,
+ int.class, int.class, int.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, int.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Integer.class));
+ mh.invokeExact((int) 0x3773470, false, (byte) 0x3773470, (char) 0x3773470,
+ (short) 0x3773470, (int) 0x3773470, (long) 0x3773470, (float) 0x3773470,
+ (double) 0x3773470, Integer.valueOf(0x3773470));
+ try {
+ mh.invoke((int) 0x3773470, false, (byte) 0x3773470, (char) 0x3773470,
+ (short) 0x3773470, (int) 0x3773470, (long) 0x3773470, (float) 0x3773470,
+ (double) 0x3773470, Long.valueOf((long) 0x3773470));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkLongCast_delegate",
+ MethodType.methodType(void.class, long.class, long.class, long.class,
+ long.class, long.class, long.class, long.class,
+ long.class, long.class, long.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, long.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Long.class));
+ long longValue = 0x770000000l;
+ mh.invokeExact((long) longValue, false, (byte) longValue, (char) longValue,
+ (short) longValue, (int) longValue, (long) longValue, (float) longValue,
+ (double) longValue, Long.valueOf(longValue));
+ try {
+ mh.invoke((long) longValue, false, (byte) longValue, (char) longValue,
+ (short) longValue, (int) longValue, (long) longValue, (float) longValue,
+ (double) longValue, Integer.valueOf(3));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkFloatCast_delegate",
+ MethodType.methodType(void.class, float.class, float.class, float.class,
+ float.class, float.class, float.class, float.class,
+ float.class, float.class, float.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, float.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Float.class));
+ float floatValue = 33333.141f;
+ mh.invokeExact(floatValue, true, (byte) floatValue, (char) floatValue, (short) floatValue,
+ (int) floatValue, (long) floatValue, floatValue, (double) floatValue,
+ Float.valueOf(floatValue));
+ try {
+ mh.invoke(floatValue, true, (byte) floatValue, (char) floatValue,
+ (short) floatValue, (int) floatValue, (long) floatValue, floatValue,
+ (double) floatValue, Integer.valueOf((int) floatValue));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkDoubleCast_delegate",
+ MethodType.methodType(void.class, double.class, double.class, double.class,
+ double.class, double.class, double.class, double.class,
+ double.class, double.class, double.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, double.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class, Double.class));
+ double doubleValue = 33333333333.141;
+ mh.invokeExact(doubleValue, true, (byte) doubleValue, (char) doubleValue,
+ (short) doubleValue, (int) doubleValue, (long) doubleValue,
+ (float) doubleValue, doubleValue, Double.valueOf(doubleValue));
+ try {
+ mh.invoke(doubleValue, true, (byte) doubleValue, (char) doubleValue,
+ (short) doubleValue, (int) doubleValue, (long) doubleValue,
+ (float) doubleValue, (double) doubleValue,
+ Integer.valueOf((int) doubleValue));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "checkBoxingCasts_delegate",
+ MethodType.methodType(void.class, boolean.class, Boolean.class, Byte.class,
+ Character.class, Short.class, Integer.class, Long.class,
+ Float.class, Double.class));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, boolean.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class));
+ mh.invokeExact(false, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0);
+ mh.invokeExact(true, true, (byte) 1, (char) 1, (short) 1, 1, 1l, 1.0f, 1.0);
+ mh.invoke(Boolean.valueOf(false), Boolean.valueOf(false), Byte.valueOf((byte) 0),
+ Character.valueOf((char) 0), Short.valueOf((short) 0), Integer.valueOf(0),
+ Long.valueOf(0l), Float.valueOf(0.0f), Double.valueOf(0.0));
+ mh.invoke(Boolean.valueOf(true), Boolean.valueOf(true), Byte.valueOf((byte) 1),
+ Character.valueOf((char) 1), Short.valueOf((short) 1), Integer.valueOf(1),
+ Long.valueOf(1l), Float.valueOf(1.0f), Double.valueOf(1.0));
+ mh = MethodHandles.explicitCastArguments(
+ target, MethodType.methodType(void.class, double.class, boolean.class, byte.class,
+ char.class, short.class, int.class, long.class,
+ float.class, double.class));
+ mh.invokeExact(0.0, false, (byte) 0, (char) 0, (short) 0, 0, 0l, 0.0f, 0.0);
+ }
+
+ static void returnVoid() {}
+
+ static boolean returnBoolean(boolean b) { return b; }
+
+ static Boolean returnBooleanObject(boolean b) { return b; }
+
+ public static void testExplicitCastReturnValues() throws Throwable {
+ MethodHandle target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "returnVoid", MethodType.methodType(void.class));
+ assertEquals(false,
+ MethodHandles
+ .explicitCastArguments(target, MethodType.methodType(boolean.class))
+ .invoke());
+ assertEquals(null,
+ MethodHandles
+ .explicitCastArguments(target, MethodType.methodType(Boolean.class))
+ .invoke());
+ assertEquals(0l,
+ MethodHandles
+ .explicitCastArguments(target, MethodType.methodType(long.class))
+ .invoke());
+ assertEquals(null,
+ MethodHandles
+ .explicitCastArguments(target, MethodType.methodType(Long.class))
+ .invoke());
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "returnBoolean",
+ MethodType.methodType(boolean.class, boolean.class));
+ assertEquals(false,
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(boolean.class, boolean.class))
+ .invoke(false));
+ assertEquals(true,
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(boolean.class, boolean.class))
+ .invoke(true));
+ assertEquals(Boolean.valueOf(false),
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(Boolean.class, boolean.class))
+ .invoke(false));
+ assertEquals(Boolean.valueOf(true),
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(Boolean.class, boolean.class))
+ .invoke(true));
+ assertEquals((byte) 0,
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(byte.class, boolean.class))
+ .invoke(false));
+ assertEquals((byte) 1,
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(byte.class, boolean.class))
+ .invoke(true));
+ try {
+ assertEquals(Byte.valueOf((byte) 0),
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(Byte.class, boolean.class))
+ .invoke(false));
+ fail();
+ } catch (ClassCastException e) {
+ }
+
+ try {
+ assertEquals(Byte.valueOf((byte) 1),
+ MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(Byte.class, boolean.class))
+ .invoke(true));
+ } catch (ClassCastException e) {
+ }
+
+ target = MethodHandles.lookup().findStatic(
+ MethodHandleCombinersTest.class, "returnBooleanObject",
+ MethodType.methodType(Boolean.class, boolean.class));
+ assertEquals(false,
+ (boolean) MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(boolean.class, boolean.class))
+ .invokeExact(false));
+ assertEquals(true,
+ (boolean) MethodHandles
+ .explicitCastArguments(target,
+ MethodType.methodType(boolean.class, boolean.class))
+ .invokeExact(true));
+ }
}
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java
index aa14bd3..cb49aef 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/AnnotatedElementParameterTest.java
@@ -114,6 +114,8 @@
void singleAnnotation(@Repeated(1) String p0) {}
+ static void staticSingleAnnotation(@Repeated(1) String p0) {}
+
static Method getMethodWithoutAnnotations() throws Exception {
return AnnotatedMethodClass.class.getDeclaredMethod("noAnnotation", String.class);
}
@@ -135,6 +137,20 @@
static Method getMethodSingleAnnotation() throws Exception {
return AnnotatedMethodClass.class.getDeclaredMethod("singleAnnotation", String.class);
}
+
+ static Method getMethodStaticSingleAnnotation() throws Exception {
+ return AnnotatedMethodClass.class.getDeclaredMethod("staticSingleAnnotation",
+ String.class);
+ }
+ }
+
+ private static abstract class AnnotatedMethodAbstractClass {
+ abstract void abstractSingleAnnotation(@Repeated(1) String p0);
+
+ static Method getMethodAbstractSingleAnnotation() throws Exception {
+ return AnnotatedMethodAbstractClass.class.getDeclaredMethod(
+ "abstractSingleAnnotation", String.class);
+ }
}
// Tests for isAnnotationPresent and getDeclaredAnnotation.
@@ -155,6 +171,12 @@
checkParameter0DeclaredAnnotation(
AnnotatedMethodClass.getMethodSingleAnnotation(),
repeated, "@Repeated(1)");
+ checkParameter0DeclaredAnnotation(
+ AnnotatedMethodClass.getMethodStaticSingleAnnotation(),
+ repeated, "@Repeated(1)");
+ checkParameter0DeclaredAnnotation(
+ AnnotatedMethodAbstractClass.getMethodAbstractSingleAnnotation(),
+ repeated, "@Repeated(1)");
Class<? extends Annotation> container = Container.class;
checkParameter0DeclaredAnnotation(
diff --git a/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java b/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java
index a07f2b3..38d9899 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java
+++ b/luni/src/test/java/libcore/java/lang/reflect/annotations/ExecutableParameterTest.java
@@ -108,6 +108,8 @@
void singleAnnotation(@Repeated(1) String p0) {}
+ static void staticSingleAnnotation(@Repeated(1) String p0) {}
+
static Method getMethodWithoutAnnotations() throws Exception {
return AnnotatedMethodClass.class.getDeclaredMethod("noAnnotation", String.class);
}
@@ -129,8 +131,23 @@
static Method getMethodSingleAnnotation() throws Exception {
return AnnotatedMethodClass.class.getDeclaredMethod("singleAnnotation", String.class);
}
+
+ static Method getMethodStaticSingleAnnotation() throws Exception {
+ return AnnotatedMethodClass.class.getDeclaredMethod("staticSingleAnnotation",
+ String.class);
+ }
}
+ private static abstract class AnnotatedMethodAbstractClass {
+ abstract void abstractSingleAnnotation(@Repeated(1) String p0);
+
+ static Method getMethodAbstractSingleAnnotation() throws Exception {
+ return AnnotatedMethodAbstractClass.class.getDeclaredMethod(
+ "abstractSingleAnnotation", String.class);
+ }
+ }
+
+
public void testMethodGetParameterAnnotations_repeated() throws Exception {
assertParameter0Annotations(
AnnotatedMethodClass.getMethodWithoutAnnotations(), EXPECT_EMPTY);
@@ -146,6 +163,13 @@
assertParameter0Annotations(
AnnotatedMethodClass.getMethodSingleAnnotation(),
"@Repeated(1)");
+ assertParameter0Annotations(
+ AnnotatedMethodClass.getMethodStaticSingleAnnotation(),
+ "@Repeated(1)");
+ assertParameter0Annotations(
+ AnnotatedMethodAbstractClass.getMethodAbstractSingleAnnotation(),
+ "@Repeated(1)");
+
}
private static class AnnotatedConstructorClass {
diff --git a/luni/src/test/java/libcore/java/net/SocketTest.java b/luni/src/test/java/libcore/java/net/SocketTest.java
index 50d8ce6..0bfd241 100644
--- a/luni/src/test/java/libcore/java/net/SocketTest.java
+++ b/luni/src/test/java/libcore/java/net/SocketTest.java
@@ -262,8 +262,11 @@
s.setTrafficClass(i);
// b/30909505
- // Linux does not set ECN bits for STREAM sockets, so these bits should be zero.
- assertEquals(i & ~INET_ECN_MASK, s.getTrafficClass());
+ // Linux does not set ECN bits for IP_TOS, but sets for IPV6_TCLASS. We should
+ // accept either output.
+ int actual = s.getTrafficClass();
+ assertTrue(i == actual || // IPV6_TCLASS
+ (actual == (i & ~INET_ECN_MASK))); // IP_TOS: ECN bits should be 0
}
}
}
diff --git a/luni/src/test/java/libcore/java/util/TimeZoneTest.java b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
index 375eb36..9f7267c 100644
--- a/luni/src/test/java/libcore/java/util/TimeZoneTest.java
+++ b/luni/src/test/java/libcore/java/util/TimeZoneTest.java
@@ -384,6 +384,18 @@
}
}
+ // http://b/33197219
+ public void testDisplayNameForNonCanonicalTimezones() {
+ TimeZone canonical = TimeZone.getTimeZone("Europe/London");
+ TimeZone nonCanonical = TimeZone.getTimeZone("GB");
+
+ // verify that GB is actually an alias for Europe/London
+ assertTrue(canonical.hasSameRules(nonCanonical));
+
+ assertEquals(canonical.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH),
+ nonCanonical.getDisplayName(true, TimeZone.LONG, Locale.ENGLISH));
+ }
+
// http://b/30937209
public void testSetDefaultDeadlock() throws InterruptedException, BrokenBarrierException {
// Since this tests a deadlock, the test has two fundamental problems:
diff --git a/luni/src/test/java/libcore/net/MimeUtilsTest.java b/luni/src/test/java/libcore/net/MimeUtilsTest.java
index ac0c017..af8f479 100644
--- a/luni/src/test/java/libcore/net/MimeUtilsTest.java
+++ b/luni/src/test/java/libcore/net/MimeUtilsTest.java
@@ -76,4 +76,13 @@
assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3gpp2"));
assertEquals("video/3gpp2", MimeUtils.guessMimeTypeFromExtension("3g2"));
}
+
+ public void test_37167977() {
+ // https://tools.ietf.org/html/rfc5334#section-10.1
+ assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("ogg"));
+ assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("oga"));
+ assertEquals("audio/ogg", MimeUtils.guessMimeTypeFromExtension("spx"));
+ assertEquals("video/ogg", MimeUtils.guessMimeTypeFromExtension("ogv"));
+ }
+
}
diff --git a/ojluni/src/main/java/java/io/Console.java b/ojluni/src/main/java/java/io/Console.java
index 2b4e4e6..b25759c 100644
--- a/ojluni/src/main/java/java/io/Console.java
+++ b/ojluni/src/main/java/java/io/Console.java
@@ -514,11 +514,10 @@
}
}
- // Android-changed: Remove SharedSecrets setup and also the shutdown
- // hook that's a no-op (but causes trouble when it's turned on).
+ // Android-removed: SharedSecrets setup and also the shutdown hook.
+ // The hook is a no-op (but causes trouble when it's turned on).
- private static Console cons;
-
+ // Android-changed: Use @hide rather than sun.misc.SharedSecrets to expose console().
/** @hide */
public static Console console() {
if (istty()) {
@@ -528,15 +527,16 @@
}
return null;
}
-
+ private static Console cons;
private native static boolean istty();
-
private Console() {
+ // BEGIN Android-changed: Support custom in/out streams for testing.
this(new FileInputStream(FileDescriptor.in), new FileOutputStream(FileDescriptor.out));
}
// Constructor for tests
private Console(InputStream inStream, OutputStream outStream) {
+ // END Android-changed: Support custom in/out streams for testing.
readLock = new Object();
writeLock = new Object();
String csname = encoding();
diff --git a/ojluni/src/main/java/java/io/DeleteOnExitHook.java b/ojluni/src/main/java/java/io/DeleteOnExitHook.java
index 447f038..e988f9b 100644
--- a/ojluni/src/main/java/java/io/DeleteOnExitHook.java
+++ b/ojluni/src/main/java/java/io/DeleteOnExitHook.java
@@ -36,11 +36,13 @@
class DeleteOnExitHook {
private static LinkedHashSet<String> files = new LinkedHashSet<>();
static {
+ // BEGIN Android-changed: Use Runtime.addShutdownHook() rather than SharedSecrets.
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
runHooks();
}
});
+ // END Android-changed: Use Runtime.addShutdownHook() rather than SharedSecrets.
}
private DeleteOnExitHook() {}
diff --git a/ojluni/src/main/java/java/io/InterruptedIOException.java b/ojluni/src/main/java/java/io/InterruptedIOException.java
index e4ed419..25569dd 100644
--- a/ojluni/src/main/java/java/io/InterruptedIOException.java
+++ b/ojluni/src/main/java/java/io/InterruptedIOException.java
@@ -74,7 +74,7 @@
public int bytesTransferred = 0;
/** @hide */
- // Android-added.
+ // Android-added: Additional constructor for internal use.
public InterruptedIOException(Throwable cause) {
super(cause);
}
@@ -84,7 +84,7 @@
*
* @hide internal use only
*/
- // Android-added.
+ // Android-added: Additional constructor for internal use.
public InterruptedIOException(String detailMessage, Throwable cause) {
super(detailMessage, cause);
}
diff --git a/ojluni/src/main/java/java/io/Serializable.java b/ojluni/src/main/java/java/io/Serializable.java
index 96ea33c..496aef7 100644
--- a/ojluni/src/main/java/java/io/Serializable.java
+++ b/ojluni/src/main/java/java/io/Serializable.java
@@ -25,6 +25,7 @@
package java.io;
+// Android-added: Notes about serialVersionUID, using serialization judiciously, JSON.
/**
* Serializability of a class is enabled by the class implementing the
* java.io.Serializable interface. Classes that do not implement this
diff --git a/ojluni/src/main/java/java/io/SerializablePermission.java b/ojluni/src/main/java/java/io/SerializablePermission.java
index e11f3ee..93bb4aa 100644
--- a/ojluni/src/main/java/java/io/SerializablePermission.java
+++ b/ojluni/src/main/java/java/io/SerializablePermission.java
@@ -27,8 +27,9 @@
import java.security.*;
+// Android-changed: Replaced with empty implementation and documented as legacy security code.
/**
- * Legacy security code; do not use.
+ * This legacy security is not supported on Android. Do not use.
*/
public final class SerializablePermission extends BasicPermission {
diff --git a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
index c67a0a4..cc24e96 100644
--- a/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
+++ b/ojluni/src/main/java/java/lang/AbstractStringBuilder.java
@@ -153,7 +153,7 @@
newCapacity = minCapacity;
}
return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0)
- ? hugeCapacity(minCapacity)
+ ? hugeCapacity(minCapacity)
: newCapacity;
}
diff --git a/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java b/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
index 756c684..9c85456 100644
--- a/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
+++ b/ojluni/src/main/java/java/lang/ArrayIndexOutOfBoundsException.java
@@ -66,16 +66,16 @@
super(s);
}
+ // Android-added: Additional constructor for internal use.
/**
- * Used internally for consistent high-quality error reporting.
* @hide
*/
public ArrayIndexOutOfBoundsException(int sourceLength, int index) {
super("length=" + sourceLength + "; index=" + index);
}
+ // Android-added: Additional constructor for internal use.
/**
- * Used internally for consistent high-quality error reporting.
* @hide
*/
public ArrayIndexOutOfBoundsException(int sourceLength, int offset,
diff --git a/ojluni/src/main/java/java/lang/Byte.java b/ojluni/src/main/java/java/lang/Byte.java
index ba2f588..d0031d0 100644
--- a/ojluni/src/main/java/java/lang/Byte.java
+++ b/ojluni/src/main/java/java/lang/Byte.java
@@ -518,7 +518,7 @@
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = -7183698231559129828L;
- // BEGIN Android-changed
+ // BEGIN Android-added: toHexString() for internal use.
/**
* @hide
*/
@@ -542,5 +542,5 @@
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z'
};
- // END Android-changed
+ // END Android-added: toHexString() for internal use.
}
diff --git a/ojluni/src/main/java/java/lang/System.java b/ojluni/src/main/java/java/lang/System.java
index 6e8f74f..ef08be0 100644
--- a/ojluni/src/main/java/java/lang/System.java
+++ b/ojluni/src/main/java/java/lang/System.java
@@ -989,7 +989,7 @@
}
p.put("os.version", info.release);
- // Undocumented Android-only properties.
+ // Android-added: Undocumented properties that exist only on Android.
p.put("android.icu.library.version", ICU.getIcuVersion());
p.put("android.icu.unicode.version", ICU.getUnicodeVersion());
p.put("android.icu.cldr.version", ICU.getCldrVersion());
diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java
index a6301b5..0419ede 100644
--- a/ojluni/src/main/java/java/lang/Thread.java
+++ b/ojluni/src/main/java/java/lang/Thread.java
@@ -1081,7 +1081,9 @@
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
- throw new IllegalArgumentException();
+ // Android-changed: Improve exception message when the new priority
+ // is out of bounds.
+ throw new IllegalArgumentException("Priority out of range: " + newPriority);
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
diff --git a/ojluni/src/main/java/java/lang/invoke/CallSite.java b/ojluni/src/main/java/java/lang/invoke/CallSite.java
index b2226bf..85b4bb9 100644
--- a/ojluni/src/main/java/java/lang/invoke/CallSite.java
+++ b/ojluni/src/main/java/java/lang/invoke/CallSite.java
@@ -260,7 +260,7 @@
}
}
- /* Android-changed: not used. */
+ // Android-changed: not used.
// /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
// /*package-private*/
// static Empty uninitializedCallSite() {
@@ -292,7 +292,7 @@
UNSAFE.putObjectVolatile(this, TARGET_OFFSET, newTarget);
}
- /* Android-changed: not used. */
+ // Android-changed: not used.
// this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
// static CallSite makeSite(MethodHandle bootstrapMethod,
// // Callee information:
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
index 6e414d0..94c9917 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodHandles.java
@@ -1978,22 +1978,18 @@
* @throws NullPointerException if either argument is null
* @throws WrongMethodTypeException if the conversion cannot be made
* @see MethodHandle#asType
- *
- * @hide
*/
public static
MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
explicitCastArgumentsChecks(target, newType);
// use the asTypeCache when possible:
MethodType oldType = target.type();
- if (oldType == newType) return target;
+ if (oldType == newType) return target;
if (oldType.explicitCastEquivalentToAsType(newType)) {
return target.asFixedArity().asType(newType);
}
- // return MethodHandleImpl.makePairwiseConvert(target, newType, false);
- // TODO(narayan): Implement explicitCastArguments, remove @hide.
- throw new UnsupportedOperationException("MethodHandles.explicitCastArguments is not implemented");
+ return new Transformers.ExplicitCastArguments(target, newType);
}
private static void explicitCastArgumentsChecks(MethodHandle target, MethodType newType) {
diff --git a/ojluni/src/main/java/java/lang/invoke/MethodType.java b/ojluni/src/main/java/java/lang/invoke/MethodType.java
index 61e0675..bfa7ccd 100644
--- a/ojluni/src/main/java/java/lang/invoke/MethodType.java
+++ b/ojluni/src/main/java/java/lang/invoke/MethodType.java
@@ -870,18 +870,20 @@
* MHs.eCA has the following "upgrades" to MH.asType:
* 1. interfaces are unchecked (that is, treated as if aliased to Object)
* Therefore, {@code Object->CharSequence} is possible in both cases but has different semantics
- * 2. the full matrix of primitive-to-primitive conversions is supported
- * Narrowing like {@code long->byte} and basic-typing like {@code boolean->int}
- * are not supported by asType, but anything supported by asType is equivalent
- * with MHs.eCE.
+ * 2a. the full matrix of primitive-to-primitive conversions is supported
+ * Narrowing like {@code long->byte} and basic-typing like {@code boolean->int}
+ * are not supported by asType, but anything supported by asType is equivalent
+ * with MHs.eCE.
+ * 2b. conversion of void->primitive means explicit cast has to insert zero/false/null.
* 3a. unboxing conversions can be followed by the full matrix of primitive conversions
* 3b. unboxing of null is permitted (creates a zero primitive value)
* Other than interfaces, reference-to-reference conversions are the same.
* Boxing primitives to references is the same for both operators.
*/
private static boolean explicitCastEquivalentToAsType(Class<?> src, Class<?> dst) {
- if (src == dst || dst == Object.class || dst == void.class) return true;
- if (src.isPrimitive()) {
+ if (src == dst || dst == Object.class || dst == void.class) {
+ return true;
+ } else if (src.isPrimitive() && src != void.class) {
// Could be a prim/prim conversion, where casting is a strict superset.
// Or a boxing conversion, which is always to an exact wrapper class.
return canConvert(src, dst);
diff --git a/ojluni/src/main/java/java/lang/invoke/Transformers.java b/ojluni/src/main/java/java/lang/invoke/Transformers.java
index 82cc797..75ee192 100644
--- a/ojluni/src/main/java/java/lang/invoke/Transformers.java
+++ b/ojluni/src/main/java/java/lang/invoke/Transformers.java
@@ -22,6 +22,7 @@
import dalvik.system.EmulatedStackFrame;
import dalvik.system.EmulatedStackFrame.Range;
+import dalvik.system.EmulatedStackFrame.StackFrameAccessor;
import dalvik.system.EmulatedStackFrame.StackFrameReader;
import dalvik.system.EmulatedStackFrame.StackFrameWriter;
import java.lang.reflect.Array;
@@ -742,11 +743,7 @@
case 'F': { o = reader.nextFloat(); break; }
case 'D': { o = reader.nextDouble(); break; }
}
- if (o != null && !elementType.isAssignableFrom(o.getClass())) {
- throw new ClassCastException(
- o.getClass() + " not assignable to " + elementType);
- }
- Array.set(arityArray, i, o);
+ Array.set(arityArray, i, elementType.cast(o));
}
return arityArray;
}
@@ -1765,4 +1762,409 @@
calleeFrame.copyReturnValueTo(stackFrame);
}
}
+
+
+ /**
+ * Implements {@link java.lang.invokeMethodHandles#explicitCastArguments()}.
+ */
+ public static class ExplicitCastArguments extends Transformer {
+ private final MethodHandle target;
+
+ public ExplicitCastArguments(MethodHandle target, MethodType type) {
+ super(type);
+ this.target = target;
+ }
+
+ @Override
+ public void transform(EmulatedStackFrame callerFrame) throws Throwable {
+ // Create a new stack frame for the target.
+ EmulatedStackFrame targetFrame = EmulatedStackFrame.create(target.type());
+
+ explicitCastArguments(callerFrame, targetFrame);
+ target.invoke(targetFrame);
+ explicitCastReturnValue(callerFrame, targetFrame);
+ }
+
+ private void explicitCastArguments(final EmulatedStackFrame callerFrame,
+ final EmulatedStackFrame targetFrame) {
+ final StackFrameReader reader = new StackFrameReader();
+ reader.attach(callerFrame);
+ final StackFrameWriter writer = new StackFrameWriter();
+ writer.attach(targetFrame);
+
+ final Class<?>[] fromTypes = type().ptypes();
+ final Class<?>[] toTypes = target.type().ptypes();
+ for (int i = 0; i < fromTypes.length; ++i) {
+ explicitCast(reader, fromTypes[i], writer, toTypes[i]);
+ }
+ }
+
+ private void explicitCastReturnValue(final EmulatedStackFrame callerFrame,
+ final EmulatedStackFrame targetFrame) {
+ Class<?> from = target.type().rtype();
+ Class<?> to = type().rtype();
+ if (to != void.class) {
+ final StackFrameWriter writer = new StackFrameWriter();
+ writer.attach(callerFrame);
+ writer.makeReturnValueAccessor();
+ if (from == void.class) {
+ if (to.isPrimitive()) {
+ unboxNull(writer, to);
+ } else {
+ writer.putNextReference(null, to);
+ }
+ } else {
+ final StackFrameReader reader = new StackFrameReader();
+ reader.attach(targetFrame);
+ reader.makeReturnValueAccessor();
+ explicitCast(reader, target.type().rtype(), writer, type().rtype());
+ }
+ }
+ }
+
+ private static void throwUnexpectedType(final Class<?> unexpectedType) {
+ throw new InternalError("Unexpected type: " + unexpectedType);
+ }
+
+ private static void explicitCastFromBoolean(boolean fromValue,
+ final StackFrameWriter writer,
+ final Class<?> to) {
+ int value = fromValue ? 1 : 0;
+ if (to == byte.class) {
+ writer.putNextByte((byte) value);
+ } else if (to == char.class) {
+ writer.putNextChar((char) value);
+ } else if (to == short.class) {
+ writer.putNextShort((short) value);
+ } else if (to == int.class) {
+ writer.putNextInt(value);
+ } else if (to == long.class) {
+ writer.putNextLong(value);
+ } else if (to == float.class) {
+ writer.putNextFloat(value);
+ } else if (to == double.class) {
+ writer.putNextDouble(value);
+ } else {
+ throwUnexpectedType(to);
+ }
+ }
+
+ /**
+ * Converts byte value to boolean according to
+ * {@link java.lang.invoke.MethodHandles#explicitCast()}
+ */
+ private static boolean toBoolean(byte value) {
+ return (value & 1) == 1;
+ }
+
+ private static byte readPrimitiveAsByte(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (byte) reader.nextByte();
+ } else if (from == char.class) {
+ return (byte) reader.nextChar();
+ } else if (from == short.class) {
+ return (byte) reader.nextShort();
+ } else if (from == int.class) {
+ return (byte) reader.nextInt();
+ } else if (from == long.class) {
+ return (byte) reader.nextLong();
+ } else if (from == float.class) {
+ return (byte) reader.nextFloat();
+ } else if (from == double.class) {
+ return (byte) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static char readPrimitiveAsChar(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (char) reader.nextByte();
+ } else if (from == char.class) {
+ return (char) reader.nextChar();
+ } else if (from == short.class) {
+ return (char) reader.nextShort();
+ } else if (from == int.class) {
+ return (char) reader.nextInt();
+ } else if (from == long.class) {
+ return (char) reader.nextLong();
+ } else if (from == float.class) {
+ return (char) reader.nextFloat();
+ } else if (from == double.class) {
+ return (char) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static short readPrimitiveAsShort(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (short) reader.nextByte();
+ } else if (from == char.class) {
+ return (short) reader.nextChar();
+ } else if (from == short.class) {
+ return (short) reader.nextShort();
+ } else if (from == int.class) {
+ return (short) reader.nextInt();
+ } else if (from == long.class) {
+ return (short) reader.nextLong();
+ } else if (from == float.class) {
+ return (short) reader.nextFloat();
+ } else if (from == double.class) {
+ return (short) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static int readPrimitiveAsInt(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (int) reader.nextByte();
+ } else if (from == char.class) {
+ return (int) reader.nextChar();
+ } else if (from == short.class) {
+ return (int) reader.nextShort();
+ } else if (from == int.class) {
+ return (int) reader.nextInt();
+ } else if (from == long.class) {
+ return (int) reader.nextLong();
+ } else if (from == float.class) {
+ return (int) reader.nextFloat();
+ } else if (from == double.class) {
+ return (int) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static long readPrimitiveAsLong(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (long) reader.nextByte();
+ } else if (from == char.class) {
+ return (long) reader.nextChar();
+ } else if (from == short.class) {
+ return (long) reader.nextShort();
+ } else if (from == int.class) {
+ return (long) reader.nextInt();
+ } else if (from == long.class) {
+ return (long) reader.nextLong();
+ } else if (from == float.class) {
+ return (long) reader.nextFloat();
+ } else if (from == double.class) {
+ return (long) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static float readPrimitiveAsFloat(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (float) reader.nextByte();
+ } else if (from == char.class) {
+ return (float) reader.nextChar();
+ } else if (from == short.class) {
+ return (float) reader.nextShort();
+ } else if (from == int.class) {
+ return (float) reader.nextInt();
+ } else if (from == long.class) {
+ return (float) reader.nextLong();
+ } else if (from == float.class) {
+ return (float) reader.nextFloat();
+ } else if (from == double.class) {
+ return (float) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static double readPrimitiveAsDouble(final StackFrameReader reader,
+ final Class<?> from) {
+ if (from == byte.class) {
+ return (double) reader.nextByte();
+ } else if (from == char.class) {
+ return (double) reader.nextChar();
+ } else if (from == short.class) {
+ return (double) reader.nextShort();
+ } else if (from == int.class) {
+ return (double) reader.nextInt();
+ } else if (from == long.class) {
+ return (double) reader.nextLong();
+ } else if (from == float.class) {
+ return (double) reader.nextFloat();
+ } else if (from == double.class) {
+ return (double) reader.nextDouble();
+ } else {
+ throwUnexpectedType(from);
+ return 0;
+ }
+ }
+
+ private static void explicitCastToBoolean(final StackFrameReader reader,
+ final Class<?> from,
+ final StackFrameWriter writer) {
+ byte byteValue = readPrimitiveAsByte(reader, from);
+ writer.putNextBoolean(toBoolean(byteValue));
+ }
+
+ private static void explicitCastPrimitives(final StackFrameReader reader,
+ final Class<?> from,
+ final StackFrameWriter writer,
+ final Class<?> to) {
+ if (to == byte.class) {
+ byte value = readPrimitiveAsByte(reader, from);
+ writer.putNextByte(value);
+ } else if (to == char.class) {
+ char value = readPrimitiveAsChar(reader, from);
+ writer.putNextChar(value);
+ } else if (to == short.class) {
+ short value = readPrimitiveAsShort(reader, from);
+ writer.putNextShort(value);
+ } else if (to == int.class) {
+ int value = readPrimitiveAsInt(reader, from);
+ writer.putNextInt(value);
+ } else if (to == long.class) {
+ long value = readPrimitiveAsLong(reader, from);
+ writer.putNextLong(value);
+ } else if (to == float.class) {
+ float value = readPrimitiveAsFloat(reader, from);
+ writer.putNextFloat(value);
+ } else if (to == double.class) {
+ double value = readPrimitiveAsDouble(reader, from);
+ writer.putNextDouble(value);
+ } else {
+ throwUnexpectedType(to);
+ }
+ }
+
+ private static void unboxNull(final StackFrameWriter writer, final Class<?> to) {
+ if (to == boolean.class) {
+ writer.putNextBoolean(false);
+ } else if (to == byte.class) {
+ writer.putNextByte((byte) 0);
+ } else if (to == char.class) {
+ writer.putNextChar((char) 0);
+ } else if (to == short.class) {
+ writer.putNextShort((short) 0);
+ } else if (to == int.class) {
+ writer.putNextInt((int) 0);
+ } else if (to == long.class) {
+ writer.putNextLong((long) 0);
+ } else if (to == float.class) {
+ writer.putNextFloat((float) 0);
+ } else if (to == double.class) {
+ writer.putNextDouble((double) 0);
+ } else {
+ throwUnexpectedType(to);
+ }
+ }
+
+ private static void unboxNonNull(final Object ref, final Class<?> from,
+ final StackFrameWriter writer, final Class<?> to) {
+ if (to == boolean.class) {
+ if (from == Boolean.class) {
+ writer.putNextBoolean((boolean) ref);
+ } else if (from == Float.class || from == Double.class) {
+ byte b = (byte) ((double) ref);
+ writer.putNextBoolean(toBoolean(b));
+ } else {
+ byte b = (byte) ((long) ref);
+ writer.putNextBoolean(toBoolean(b));
+ }
+ } else if (to == byte.class) {
+ writer.putNextByte((byte) ref);
+ } else if (to == char.class) {
+ writer.putNextChar((char) ref);
+ } else if (to == short.class) {
+ writer.putNextShort((short) ref);
+ } else if (to == int.class) {
+ writer.putNextInt((int) ref);
+ } else if (to == long.class) {
+ writer.putNextLong((long) ref);
+ } else if (to == float.class) {
+ writer.putNextFloat((float) ref);
+ } else if (to == double.class) {
+ writer.putNextDouble((double) ref);
+ } else {
+ throwUnexpectedType(to);
+ }
+ }
+
+ private static void unbox(final Object ref, final Class<?> from,
+ final StackFrameWriter writer, final Class<?> to) {
+ if (ref == null) {
+ unboxNull(writer, to);
+ } else {
+ unboxNonNull(ref, from, writer, to);
+ }
+ }
+
+ private static void box(final StackFrameReader reader, final Class<?> from,
+ final StackFrameWriter writer, final Class<?> to) {
+ Object boxed = null;
+ if (from == boolean.class) {
+ boxed = Boolean.valueOf(reader.nextBoolean());
+ } else if (from == byte.class) {
+ boxed = Byte.valueOf(reader.nextByte());
+ } else if (from == char.class) {
+ boxed = Character.valueOf(reader.nextChar());
+ } else if (from == short.class) {
+ boxed = Short.valueOf(reader.nextShort());
+ } else if (from == int.class) {
+ boxed = Integer.valueOf(reader.nextInt());
+ } else if (from == long.class) {
+ boxed = Long.valueOf(reader.nextLong());
+ } else if (from == float.class) {
+ boxed = Float.valueOf(reader.nextFloat());
+ } else if (from == double.class) {
+ boxed = Double.valueOf(reader.nextDouble());
+ } else {
+ throwUnexpectedType(from);
+ }
+ writer.putNextReference(to.cast(boxed), to);
+ }
+
+ private static void explicitCast(final StackFrameReader reader, final Class<?> from,
+ final StackFrameWriter writer, final Class<?> to) {
+ if (from.equals(to)) {
+ StackFrameAccessor.copyNext(reader, writer, from);
+ } else if (!from.isPrimitive()) {
+ Object ref = reader.nextReference(from);
+ if (to.isInterface()) {
+ // Pass from without a cast according to description for
+ // {@link java.lang.invoke.MethodHandles#explicitCastArguments()}.
+ writer.putNextReference(ref, to);
+ } else if (!to.isPrimitive()) {
+ // |to| is a reference type, perform class cast check.
+ writer.putNextReference(to.cast(ref), to);
+ } else {
+ // |from| is a reference type, |to| is a primitive type,
+ unbox(ref, from, writer, to);
+ }
+ } else if (to.isPrimitive()) {
+ // |from| and |to| are primitive types.
+ if (from == boolean.class) {
+ explicitCastFromBoolean(reader.nextBoolean(), writer, to);
+ } else if (to == boolean.class) {
+ explicitCastToBoolean(reader, from, writer);
+ } else {
+ explicitCastPrimitives(reader, from, writer, to);
+ }
+ } else {
+ // |from| is a primitive type, |to| is a reference type.
+ box(reader, from, writer, to);
+ }
+ }
+ }
}
diff --git a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
index 8c687ec..16cf18c 100644
--- a/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/AbstractPlainSocketImpl.java
@@ -49,8 +49,8 @@
{
/* instance variable for SO_TIMEOUT */
int timeout; // timeout in millisec
- // traffic class
- private int trafficClass;
+ // Android-removed: traffic class is set through socket
+ // private int trafficClass;
private boolean shut_rd = false;
private boolean shut_wr = false;
@@ -205,17 +205,19 @@
if (isClosedOrPending()) {
throw new SocketException("Socket Closed");
}
+ // Android-removed: Logic dealing with value type moved to socketSetOption.
+ /*
boolean on = true;
switch (opt) {
/* check type safety b4 going native. These should never
* fail, since only java.Socket* has access to
* PlainSocketImpl.setOption().
- */
+ *
case SO_LINGER:
if (val == null || (!(val instanceof Integer) && !(val instanceof Boolean)))
throw new SocketException("Bad parameter for option");
if (val instanceof Boolean) {
- /* true only if disabling - enabling should be Integer */
+ /* true only if disabling - enabling should be Integer *
on = false;
}
break;
@@ -267,6 +269,11 @@
throw new SocketException("unrecognized TCP option: " + opt);
}
socketSetOption(opt, on, val);
+ */
+ if (opt == SO_TIMEOUT) {
+ timeout = (Integer) val;
+ }
+ socketSetOption(opt, val);
}
public Object getOption(int opt) throws SocketException {
if (isClosedOrPending()) {
@@ -275,6 +282,8 @@
if (opt == SO_TIMEOUT) {
return new Integer(timeout);
}
+ // Android-removed: Logic dealing with value type moved to socketGetOption.
+ /*
int ret = 0;
/*
* The native socketGetOption() knows about 3 options.
@@ -282,7 +291,7 @@
* to what we're asking. A return of -1 means it understands
* the option but its turned off. It will raise a SocketException
* if "opt" isn't one it understands.
- */
+ *
switch (opt) {
case TCP_NODELAY:
@@ -324,6 +333,8 @@
default:
return null;
}
+ */
+ return socketGetOption(opt);
}
/**
@@ -725,9 +736,12 @@
throws IOException;
abstract void socketShutdown(int howto)
throws IOException;
- abstract void socketSetOption(int cmd, boolean on, Object value)
- throws SocketException;
- abstract int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
+
+ // Android-changed: Method signature changed, socket{Get,Set}Option work directly with Object
+ // values.
+ abstract void socketSetOption(int cmd, Object value) throws SocketException;
+ abstract Object socketGetOption(int opt) throws SocketException;
+
abstract void socketSendUrgentData(int data)
throws IOException;
diff --git a/ojluni/src/main/java/java/net/DatagramSocket.java b/ojluni/src/main/java/java/net/DatagramSocket.java
index 34f3a2d..31a4db4 100755
--- a/ojluni/src/main/java/java/net/DatagramSocket.java
+++ b/ojluni/src/main/java/java/net/DatagramSocket.java
@@ -1347,17 +1347,16 @@
factory = fac;
}
+ // Android-added: for testing and internal use.
/**
- * Android-added: for testing and internal use.
- *
* @hide internal use only
*/
public FileDescriptor getFileDescriptor$() {
return impl.fd;
}
+ // Android-added: setNetworkInterface() to set the network interface used by this socket.
/**
- * Android-added:
* Sets the network interface used by this socket. Any packets sent
* via this socket are transmitted via the specified interface. Any
* packets received by this socket will come from the specified
diff --git a/ojluni/src/main/java/java/net/Inet6Address.java b/ojluni/src/main/java/java/net/Inet6Address.java
index 51b0927..ee946ee 100644
--- a/ojluni/src/main/java/java/net/Inet6Address.java
+++ b/ojluni/src/main/java/java/net/Inet6Address.java
@@ -262,7 +262,8 @@
}
}
- /* ----- Android-removed -----
+ // Android-removed: getnameinfo returns smarter representations than getHostAddress()
+ /*
String getHostAddress() {
String s = numericToTextFormat(ipaddress);
if (scope_ifname != null) { // must check this first
@@ -271,7 +272,8 @@
s = s + "%" + scope_id;
}
return s;
- } */
+ }
+ */
public boolean equals(Object o) {
if (! (o instanceof Inet6AddressHolder)) {
@@ -870,7 +872,7 @@
*/
@Override
public String getHostAddress() {
- // Android-changed: getnameinfo returns smarter representations
+ // Android-changed: getnameinfo returns smarter representations than getHostAddress()
// return holder6.getHostAddress();
return Libcore.os.getnameinfo(this, NI_NUMERICHOST); // Can't throw.
}
diff --git a/ojluni/src/main/java/java/net/PlainSocketImpl.java b/ojluni/src/main/java/java/net/PlainSocketImpl.java
index f02006d..656defc 100644
--- a/ojluni/src/main/java/java/net/PlainSocketImpl.java
+++ b/ojluni/src/main/java/java/net/PlainSocketImpl.java
@@ -101,9 +101,9 @@
return (T)flow;
}
- protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
+ protected void socketSetOption(int opt, Object val) throws SocketException {
try {
- socketSetOption0(opt, b, val);
+ socketSetOption0(opt, val);
} catch (SocketException se) {
if (socket == null || !socket.isConnected())
throw se;
@@ -268,10 +268,18 @@
}
}
- native void socketSetOption0(int cmd, boolean on, Object value)
- throws SocketException;
+ void socketSetOption0(int cmd, Object value) throws SocketException {
+ // OpenJDK does not set SO_TIMEOUT on Linux.
+ if (cmd == SO_TIMEOUT) {
+ return;
+ }
- native int socketGetOption(int opt, Object iaContainerObj) throws SocketException;
+ IoBridge.setSocketOption(fd, cmd, value);
+ }
+
+ Object socketGetOption(int opt) throws SocketException {
+ return IoBridge.getSocketOption(fd, opt);
+ }
void socketSendUrgentData(int data) throws IOException {
if (fd == null || !fd.valid()) {
diff --git a/ojluni/src/main/java/java/net/ServerSocket.java b/ojluni/src/main/java/java/net/ServerSocket.java
index 670acf2..20ae95a 100644
--- a/ojluni/src/main/java/java/net/ServerSocket.java
+++ b/ojluni/src/main/java/java/net/ServerSocket.java
@@ -922,9 +922,8 @@
/* Not implemented yet */
}
+ // Android-added: for testing and internal use.
/**
- * Android-added: for testing and internal use.
- *
* @hide internal use only
*/
public FileDescriptor getFileDescriptor$() {
diff --git a/ojluni/src/main/java/java/net/Socket.java b/ojluni/src/main/java/java/net/Socket.java
index 9d566b1..03e2b71 100644
--- a/ojluni/src/main/java/java/net/Socket.java
+++ b/ojluni/src/main/java/java/net/Socket.java
@@ -1768,9 +1768,8 @@
/* Not implemented yet */
}
+ // Android-added: for testing and internal use.
/**
- * Android-added: for testing and internal use.
- *
* @hide internal use only
*/
public FileDescriptor getFileDescriptor$() {
diff --git a/ojluni/src/main/java/java/net/SocketTimeoutException.java b/ojluni/src/main/java/java/net/SocketTimeoutException.java
index 3b5b50a..2c61415 100644
--- a/ojluni/src/main/java/java/net/SocketTimeoutException.java
+++ b/ojluni/src/main/java/java/net/SocketTimeoutException.java
@@ -50,11 +50,13 @@
public SocketTimeoutException() {}
/** @hide */
+ // Android-added: Additional constructor for internal use.
public SocketTimeoutException(Throwable cause) {
super(cause);
}
/** @hide */
+ // Android-added: Additional constructor for internal use.
public SocketTimeoutException(String msg, Throwable cause) {
super(msg, cause);
}
diff --git a/ojluni/src/main/java/java/net/SocksSocketImpl.java b/ojluni/src/main/java/java/net/SocksSocketImpl.java
index f1b29b0..a81e219 100644
--- a/ojluni/src/main/java/java/net/SocksSocketImpl.java
+++ b/ojluni/src/main/java/java/net/SocksSocketImpl.java
@@ -347,8 +347,9 @@
epoint.getPort());
}
if (server == null) {
+ // Android-removed: Logic to establish proxy connection based on default ProxySelector
/*
- * Android-changed: Removed code that tried to establish proxy connection if
+ * Removed code that tried to establish proxy connection if
* ProxySelector#getDefault() is not null.
* This was never the case in previous android releases, was causing
* issues and therefore was removed.
diff --git a/ojluni/src/main/java/java/security/KeyPairGenerator.java b/ojluni/src/main/java/java/security/KeyPairGenerator.java
index 1e46cee..68ab5e9 100644
--- a/ojluni/src/main/java/java/security/KeyPairGenerator.java
+++ b/ojluni/src/main/java/java/security/KeyPairGenerator.java
@@ -34,11 +34,6 @@
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
-/*
-Android-removed: this debugging mechanism is not supported in Android.
-import sun.security.util.Debug;
-*/
-
/**
* The KeyPairGenerator class is used to generate pairs of
* public and private keys. Key pair generators are constructed using the
@@ -149,8 +144,8 @@
public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
+ // Android-removed: this debugging mechanism is not used in Android.
/*
- Android-removed: this debugging mechanism is not supported in Android.
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -199,8 +194,8 @@
}
kpg.provider = instance.provider;
+ // Android-removed: this debugging mechanism is not used in Android.
/*
- Android-removed: this debugging mechanism is not supported in Android.
if (!skipDebug && pdebug != null) {
pdebug.println("KeyPairGenerator." + algorithm +
" algorithm from: " + kpg.provider.getName());
@@ -598,8 +593,8 @@
this.serviceIterator = serviceIterator;
initType = I_NONE;
+ // Android-removed: this debugging mechanism is not used in Android.
/*
- Android-removed: this debugging mechanism is not supported in Android.
if (!skipDebug && pdebug != null) {
pdebug.println("KeyPairGenerator." + algorithm +
" algorithm from: " + provider.getName());
diff --git a/ojluni/src/main/java/java/security/MessageDigest.java b/ojluni/src/main/java/java/security/MessageDigest.java
index df6c456..5f586ac 100644
--- a/ojluni/src/main/java/java/security/MessageDigest.java
+++ b/ojluni/src/main/java/java/security/MessageDigest.java
@@ -35,10 +35,6 @@
import java.nio.ByteBuffer;
-/*
-Android-removed: this debugging mechanism is not available in Android.
-import sun.security.util.Debug;
-*/
/**
* This MessageDigest class provides applications the functionality of a
* message digest algorithm, such as SHA-1 or SHA-256.
@@ -134,8 +130,8 @@
public abstract class MessageDigest extends MessageDigestSpi {
+ // Android-removed: this debugging mechanism is not used in Android.
/*
- Android-removed: this debugging mechanism is not available in Android.
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -205,8 +201,8 @@
}
md.provider = (Provider)objs[1];
+ // Android-removed: this debugging mechanism is not used in Android.
/*
- Android-removed: this debugging mechanism is not available in Android.
if (!skipDebug && pdebug != null) {
pdebug.println("MessageDigest." + algorithm +
" algorithm from: " + md.provider.getName());
diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java
index d38882a..d1fbd29 100644
--- a/ojluni/src/main/java/java/security/Provider.java
+++ b/ojluni/src/main/java/java/security/Provider.java
@@ -977,7 +977,7 @@
if (typeAndAlg == null) {
return;
}
- String type = typeAndAlg[0];
+ String type = getEngineName(typeAndAlg[0]);
String aliasAlg = typeAndAlg[1].intern();
ServiceKey key = new ServiceKey(type, stdAlg, true);
Service s = legacyMap.get(key);
@@ -997,7 +997,7 @@
int i = typeAndAlg[1].indexOf(' ');
if (i == -1) {
// e.g. put("MessageDigest.SHA-1", "sun.security.provider.SHA");
- String type = typeAndAlg[0];
+ String type = getEngineName(typeAndAlg[0]);
String stdAlg = typeAndAlg[1].intern();
String className = value;
ServiceKey key = new ServiceKey(type, stdAlg, true);
@@ -1012,7 +1012,7 @@
} else { // attribute
// e.g. put("MessageDigest.SHA-1 ImplementedIn", "Software");
String attributeValue = value;
- String type = typeAndAlg[0];
+ String type = getEngineName(typeAndAlg[0]);
String attributeString = typeAndAlg[1];
String stdAlg = attributeString.substring(0, i).intern();
String attributeName = attributeString.substring(i + 1);
@@ -1324,10 +1324,8 @@
private static void addEngine(String name, boolean sp, String paramName) {
EngineDescription ed = new EngineDescription(name, sp, paramName);
- // NOTE: The original OpenJDK code supported case-insensitive lookups on the list
- // of known engines.
- //
- // knownEngines.put(name.toLowerCase(ENGLISH), ed);
+ // also index by canonical name to avoid toLowerCase() for some lookups
+ knownEngines.put(name.toLowerCase(ENGLISH), ed);
knownEngines.put(name, ed);
}
@@ -1378,6 +1376,17 @@
"java.lang.Object");
}
+ // get the "standard" (mixed-case) engine name for arbitary case engine name
+ // if there is no known engine by that name, return s
+ private static String getEngineName(String s) {
+ // try original case first, usually correct
+ EngineDescription e = knownEngines.get(s);
+ if (e == null) {
+ e = knownEngines.get(s.toLowerCase(ENGLISH));
+ }
+ return (e == null) ? s : e.name;
+ }
+
/**
* The description of a security service. It encapsulates the properties
* of a service and contains a factory method to obtain new implementation
@@ -1481,8 +1490,7 @@
throw new NullPointerException();
}
this.provider = provider;
- // Android-changed.
- this.type = type;
+ this.type = getEngineName(type);
this.algorithm = algorithm;
this.className = className;
if (aliases == null) {
diff --git a/ojluni/src/main/java/java/security/SecureRandom.java b/ojluni/src/main/java/java/security/SecureRandom.java
index 78eac68..f512264 100644
--- a/ojluni/src/main/java/java/security/SecureRandom.java
+++ b/ojluni/src/main/java/java/security/SecureRandom.java
@@ -99,7 +99,7 @@
public class SecureRandom extends java.util.Random {
- // Android-removed: this debugging mechanism is not supported in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
/*
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
diff --git a/ojluni/src/main/java/java/text/DateFormatSymbols.java b/ojluni/src/main/java/java/text/DateFormatSymbols.java
index aa57aad..96a966c 100644
--- a/ojluni/src/main/java/java/text/DateFormatSymbols.java
+++ b/ojluni/src/main/java/java/text/DateFormatSymbols.java
@@ -865,35 +865,17 @@
}
}
+ // BEGIN Android-changed: extract initialization of zoneStrings to separate method.
private final synchronized String[][] internalZoneStrings() {
if (zoneStrings == null) {
zoneStrings = TimeZoneNames.getZoneStrings(locale);
- // If icu4c doesn't have a name, our array contains a null. TimeZone.getDisplayName
- // knows how to format GMT offsets (and, unlike icu4c, has accurate data). http://b/8128460.
- for (String[] zone : zoneStrings) {
- String id = zone[0];
- if (zone[1] == null) {
- zone[1] =
- TimeZone.getTimeZone(id).getDisplayName(false, TimeZone.LONG, locale);
- }
- if (zone[2] == null) {
- zone[2] =
- TimeZone.getTimeZone(id).getDisplayName(false, TimeZone.SHORT, locale);
- }
- if (zone[3] == null) {
- zone[3] = TimeZone.getTimeZone(id).getDisplayName(true, TimeZone.LONG, locale);
- }
- if (zone[4] == null) {
- zone[4] =
- TimeZone.getTimeZone(id).getDisplayName(true, TimeZone.SHORT, locale);
- }
- }
}
return zoneStrings;
}
private final String[][] getZoneStringsImpl(boolean needsCopy) {
String[][] zoneStrings = internalZoneStrings();
+ // END Android-changed: extract initialization of zoneStrings to separate method.
if (!needsCopy) {
return zoneStrings;
@@ -964,6 +946,7 @@
* @since 1.6
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
+ // Android-changed: extract initialization of zoneStrings to separate method.
internalZoneStrings();
stream.defaultWriteObject();
}
diff --git a/ojluni/src/main/java/java/time/chrono/HijrahChronology.java b/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
index 98b79c4..e7b3554 100644
--- a/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
+++ b/ojluni/src/main/java/java/time/chrono/HijrahChronology.java
@@ -544,7 +544,7 @@
//-----------------------------------------------------------------------
@Override
public boolean isLeapYear(long prolepticYear) {
- checkCalendarInit();
+ checkCalendarInit();
if (prolepticYear < getMinimumYear() || prolepticYear > getMaximumYear()) {
return false;
}
diff --git a/ojluni/src/main/java/java/util/ArrayList.java b/ojluni/src/main/java/java/util/ArrayList.java
index dd465c9..d65bf1f 100644
--- a/ojluni/src/main/java/java/util/ArrayList.java
+++ b/ojluni/src/main/java/java/util/ArrayList.java
@@ -103,8 +103,8 @@
* @see Vector
* @since 1.2
*/
+// Android-changed: Inlined methods; CME in iterators; throw AIOOBE when toIndex < fromIndex.
/*
- * Android-changed:
* - AOSP commit 3be987f0f18648b3c532c8b89d09505e18594241
* Inline for improved performance:
* - checkForComodification
diff --git a/ojluni/src/main/java/java/util/Arrays.java b/ojluni/src/main/java/java/util/Arrays.java
index b4f52a4..72c5f93 100644
--- a/ojluni/src/main/java/java/util/Arrays.java
+++ b/ojluni/src/main/java/java/util/Arrays.java
@@ -124,11 +124,10 @@
}
}
+ // BEGIN Android-added: checkOffsetAndCount() helper method for AIOOBE enforcement.
/**
* Checks that the range described by {@code offset} and {@code count} doesn't exceed
* {@code arrayLength}.
- *
- * Android-changed.
* @hide
*/
public static void checkOffsetAndCount(int arrayLength, int offset, int count) {
@@ -137,6 +136,7 @@
count);
}
}
+ // END Android-added: checkOffsetAndCount() helper method for AIOOBE enforcement.
/*
* Sorting methods. Note that all public "sort" methods take the
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 4818ee6..5d0325f 100644
--- a/ojluni/src/main/java/java/util/Collections.java
+++ b/ojluni/src/main/java/java/util/Collections.java
@@ -151,7 +151,7 @@
@SuppressWarnings("unchecked")
public static <T extends Comparable<? super T>> void sort(List<T> list) {
// Android-changed: Call sort(list, null) here to be consistent
- // with that method's (Android-changed) behavior.
+ // with that method's (Android changed) behavior.
// list.sort(null);
sort(list, null);
}
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index 3b5c3af..aec40bc 100644
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -190,7 +190,7 @@
* LinkedHashMap.Entry is now treated as intermediary node class
* that can also be converted to tree form.
*
- * BEGIN Android-changed
+ // BEGIN Android-changed
* LinkedHashMapEntry should not be renamed. Specifically, for
* source compatibility with earlier versions of Android, this
* nested class must not be named "Entry". Otherwise, it would
@@ -201,7 +201,7 @@
* To compile, that code snippet's "LinkedHashMap.Entry" must
* mean java.util.Map.Entry which is the compile time type of
* entrySet()'s elements.
- * END Android-changed
+ // END Android-changed
*
* The changes in node classes also require using two fields
* (head, tail) rather than a pointer to a header node to maintain
diff --git a/ojluni/src/main/java/java/util/Locale.java b/ojluni/src/main/java/java/util/Locale.java
index 437cc66..9bd3126 100644
--- a/ojluni/src/main/java/java/util/Locale.java
+++ b/ojluni/src/main/java/java/util/Locale.java
@@ -512,6 +512,14 @@
* <td><a href="http://site.icu-project.org/download/55">ICU 55.1</a></td>
* <td><a href="http://cldr.unicode.org/index/downloads/cldr-27">CLDR 27.0.1</a></td>
* <td><a href="http://www.unicode.org/versions/Unicode7.0.0/">Unicode 7.0</a></td></tr>
+ * <tr><td>Android 7.0 (Nougat)</td>
+ * <td><a href="http://site.icu-project.org/download/56">ICU 56.1</a></td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-28">CLDR 28</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode8.0.0/">Unicode 8.0</a></td></tr>
+ * <tr><td>Android 8.0 (TBD)</td>
+ * <td><a href="http://site.icu-project.org/download/58">ICU 58.2</a></td>
+ * <td><a href="http://cldr.unicode.org/index/downloads/cldr-30">CLDR 30.0.3</a></td>
+ * <td><a href="http://www.unicode.org/versions/Unicode9.0.0/">Unicode 9.0</a></td></tr>
* </table>
*
* <a name="default_locale"></a><h4>Be wary of the default locale</h3>
diff --git a/ojluni/src/main/java/java/util/Optional.java b/ojluni/src/main/java/java/util/Optional.java
index 10b7923..bce8ff9 100644
--- a/ojluni/src/main/java/java/util/Optional.java
+++ b/ojluni/src/main/java/java/util/Optional.java
@@ -29,6 +29,7 @@
import java.util.function.Predicate;
import java.util.function.Supplier;
+// Android-changed: removed ValueBased paragraph.
/**
* A container object which may or may not contain a non-null value.
* If a value is present, {@code isPresent()} will return {@code true} and
diff --git a/ojluni/src/main/java/java/util/OptionalDouble.java b/ojluni/src/main/java/java/util/OptionalDouble.java
index ead3c91..7112df1 100644
--- a/ojluni/src/main/java/java/util/OptionalDouble.java
+++ b/ojluni/src/main/java/java/util/OptionalDouble.java
@@ -28,6 +28,7 @@
import java.util.function.DoubleSupplier;
import java.util.function.Supplier;
+// Android-changed: removed ValueBased paragraph.
/**
* A container object which may or may not contain a {@code double} value.
* If a value is present, {@code isPresent()} will return {@code true} and
diff --git a/ojluni/src/main/java/java/util/OptionalInt.java b/ojluni/src/main/java/java/util/OptionalInt.java
index 23c8b8c..7907328 100644
--- a/ojluni/src/main/java/java/util/OptionalInt.java
+++ b/ojluni/src/main/java/java/util/OptionalInt.java
@@ -28,6 +28,7 @@
import java.util.function.IntSupplier;
import java.util.function.Supplier;
+// Android-changed: removed ValueBased paragraph.
/**
* A container object which may or may not contain a {@code int} value.
* If a value is present, {@code isPresent()} will return {@code true} and
diff --git a/ojluni/src/main/java/java/util/OptionalLong.java b/ojluni/src/main/java/java/util/OptionalLong.java
index 21aa70e..b337d83 100644
--- a/ojluni/src/main/java/java/util/OptionalLong.java
+++ b/ojluni/src/main/java/java/util/OptionalLong.java
@@ -28,6 +28,7 @@
import java.util.function.LongSupplier;
import java.util.function.Supplier;
+// Android-changed: removed ValueBased paragraph.
/**
* A container object which may or may not contain a {@code long} value.
* If a value is present, {@code isPresent()} will return {@code true} and
diff --git a/ojluni/src/main/java/java/util/ResourceBundle.java b/ojluni/src/main/java/java/util/ResourceBundle.java
index 886ffc1..6fff252 100644
--- a/ojluni/src/main/java/java/util/ResourceBundle.java
+++ b/ojluni/src/main/java/java/util/ResourceBundle.java
@@ -360,7 +360,8 @@
*/
private volatile Set<String> keySet;
- /* Android-changed: Removed used of ResourceBundleControlProvider.
+ // Android-changed: Removed use of ResourceBundleControlProvider.
+ /*
private static final List<ResourceBundleControlProvider> providers;
static {
diff --git a/ojluni/src/main/java/java/util/TimeZone.java b/ojluni/src/main/java/java/util/TimeZone.java
index 28ad0ca..6ad180b 100644
--- a/ojluni/src/main/java/java/util/TimeZone.java
+++ b/ojluni/src/main/java/java/util/TimeZone.java
@@ -39,20 +39,15 @@
package java.util;
+import org.apache.harmony.luni.internal.util.TimezoneGetter;
+import android.icu.text.TimeZoneNames;
import java.io.IOException;
import java.io.Serializable;
import java.time.ZoneId;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.lang.ref.SoftReference;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.concurrent.ConcurrentHashMap;
-import libcore.icu.TimeZoneNames;
import libcore.io.IoUtils;
import libcore.util.ZoneInfoDB;
-import sun.security.action.GetPropertyAction;
-import org.apache.harmony.luni.internal.util.TimezoneGetter;
/**
* <code>TimeZone</code> represents a time zone offset, and also figures out daylight
@@ -387,15 +382,30 @@
* @param locale the display locale.
*/
public String getDisplayName(boolean daylightTime, int style, Locale locale) {
- if (style != SHORT && style != LONG) {
- throw new IllegalArgumentException("Illegal style: " + style);
+ // BEGIN Android-changed: implement using android.icu.text.TimeZoneNames
+ TimeZoneNames.NameType nameType;
+ switch (style) {
+ case SHORT:
+ nameType = daylightTime
+ ? TimeZoneNames.NameType.SHORT_DAYLIGHT
+ : TimeZoneNames.NameType.SHORT_STANDARD;
+ break;
+ case LONG:
+ nameType = daylightTime
+ ? TimeZoneNames.NameType.LONG_DAYLIGHT
+ : TimeZoneNames.NameType.LONG_STANDARD;
+ break;
+ default:
+ throw new IllegalArgumentException("Illegal style: " + style);
}
-
- // Android-changed: implement using libcore.icu.TimeZoneNames
- String[][] zoneStrings = TimeZoneNames.getZoneStrings(locale);
- String result = TimeZoneNames.getDisplayName(zoneStrings, getID(), daylightTime, style);
- if (result != null) {
- return result;
+ String canonicalID = android.icu.util.TimeZone.getCanonicalID(getID());
+ if (canonicalID != null) {
+ TimeZoneNames names = TimeZoneNames.getInstance(locale);
+ long now = System.currentTimeMillis();
+ String displayName = names.getDisplayName(canonicalID, nameType, now);
+ if (displayName != null) {
+ return displayName;
+ }
}
// We get here if this is a custom timezone or ICU doesn't have name data for the specific
@@ -406,8 +416,10 @@
}
return createGmtOffsetString(true /* includeGmt */, true /* includeMinuteSeparator */,
offsetMillis);
+ // END Android-changed: implement using android.icu.text.TimeZoneNames
}
+ // BEGIN Android-added: utility method to format an offset as a GMT offset string.
/**
* Returns a string representation of an offset from UTC.
*
@@ -448,6 +460,7 @@
}
builder.append(string);
}
+ // END Android-added: utility method to format an offset as a GMT offset string.
/**
* Returns the amount of time to be added to local standard time
diff --git a/ojluni/src/main/java/java/util/XMLUtils.java b/ojluni/src/main/java/java/util/XMLUtils.java
index b7133dc..8f061e5 100644
--- a/ojluni/src/main/java/java/util/XMLUtils.java
+++ b/ojluni/src/main/java/java/util/XMLUtils.java
@@ -92,7 +92,7 @@
{
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace(true);
- // Android-chanaged: We don't currently have a validating document builder.
+ // Android-changed: We don't currently have a validating document builder.
// Revert this if the situation changes.
//
// dbf.setValidating(true);
diff --git a/ojluni/src/main/java/java/util/logging/Level.java b/ojluni/src/main/java/java/util/logging/Level.java
index afc7035..c03b171 100644
--- a/ojluni/src/main/java/java/util/logging/Level.java
+++ b/ojluni/src/main/java/java/util/logging/Level.java
@@ -262,7 +262,7 @@
}
private String computeLocalizedLevelName(Locale newLocale) {
- // Android-change: Use Thread.currentThread().getContextClassLoader(),
+ // Android-changed: Use Thread.currentThread().getContextClassLoader(),
// otherwise we might get a BootClassLoader.
ResourceBundle rb = ResourceBundle.getBundle(resourceBundleName, newLocale,
Thread.currentThread().getContextClassLoader());
diff --git a/ojluni/src/main/java/javax/crypto/Cipher.java b/ojluni/src/main/java/javax/crypto/Cipher.java
index c2a2183..c707899 100644
--- a/ojluni/src/main/java/javax/crypto/Cipher.java
+++ b/ojluni/src/main/java/javax/crypto/Cipher.java
@@ -44,9 +44,6 @@
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
-/* Android-removed: this debugging mechanism is not used in Android
-import sun.security.util.Debug;
-*/
import sun.security.jca.*;
/**
@@ -230,7 +227,8 @@
public class Cipher {
- /* Android-removed: this debugging mechanism is not used in Android
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -835,7 +833,8 @@
initialized = true;
this.opmode = opmode;
- /* Android-removed: this debugging mechanism is not used in Android
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Cipher." + transformation + " " +
getOpmodeString(opmode) + " algorithm from: " +
@@ -975,7 +974,8 @@
initialized = true;
this.opmode = opmode;
- /* Android-removed: this debugging mechanism is not used in Android
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Cipher." + transformation + " " +
getOpmodeString(opmode) + " algorithm from: " +
@@ -1115,7 +1115,8 @@
initialized = true;
this.opmode = opmode;
- /* Android-removed: this debugging mechanism is not used in Android
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Cipher." + transformation + " " +
getOpmodeString(opmode) + " algorithm from: " +
@@ -1301,7 +1302,8 @@
initialized = true;
this.opmode = opmode;
- /* Android-removed: this debugging mechanism is not used in Android
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Cipher." + transformation + " " +
getOpmodeString(opmode) + " algorithm from: " +
@@ -2171,8 +2173,8 @@
*/
public static final int getMaxAllowedKeyLength(String transformation)
throws NoSuchAlgorithmException {
- // Android-changed: Remove references to CryptoPermission and throw early
- // if transformation == null or isn't valid.
+ // Android-changed: Remove references to CryptoPermission.
+ // Throw early if transformation == null or isn't valid.
//
// CryptoPermission cp = getConfiguredPermission(transformation);
// return cp.getMaxAllowedKeyLength();
@@ -2204,8 +2206,8 @@
*/
public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
String transformation) throws NoSuchAlgorithmException {
- // Android-changed: Remove references to CryptoPermission and throw early
- // if transformation == null or isn't valid.
+ // Android-changed: Remove references to CryptoPermission.
+ // Throw early if transformation == null or isn't valid.
//
// CryptoPermission cp = getConfiguredPermission(transformation);
// return cp.getAlgorithmParameterSpec();
diff --git a/ojluni/src/main/java/javax/crypto/KeyAgreement.java b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
index 8a0b1c1..7c29102 100644
--- a/ojluni/src/main/java/javax/crypto/KeyAgreement.java
+++ b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
@@ -32,9 +32,6 @@
import java.security.Provider.Service;
import java.security.spec.*;
-/* Android-removed: this debugging mechanism is not used in Android.
-import sun.security.util.Debug;
-*/
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
@@ -91,7 +88,8 @@
public class KeyAgreement {
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -293,7 +291,8 @@
if (spi != null) {
return;
}
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
@@ -463,7 +462,8 @@
}
}
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
this.provider.getName());
@@ -526,7 +526,8 @@
chooseProvider(I_PARAMS, key, params, random);
}
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyAgreement." + algorithm + " algorithm from: " +
this.provider.getName());
diff --git a/ojluni/src/main/java/javax/crypto/KeyGenerator.java b/ojluni/src/main/java/javax/crypto/KeyGenerator.java
index 8a54e5c..5dfde97 100644
--- a/ojluni/src/main/java/javax/crypto/KeyGenerator.java
+++ b/ojluni/src/main/java/javax/crypto/KeyGenerator.java
@@ -33,9 +33,6 @@
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
-/* Android-removed: this debugging mechanism is not used in Android.
-import sun.security.util.Debug;
-*/
/**
* This class provides the functionality of a secret (symmetric) key generator.
@@ -167,7 +164,8 @@
public class KeyGenerator {
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -212,7 +210,8 @@
this.provider = provider;
this.algorithm = algorithm;
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
this.provider.getName());
@@ -232,7 +231,8 @@
(algorithm + " KeyGenerator not available");
}
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("KeyGenerator." + algorithm + " algorithm from: " +
this.provider.getName());
diff --git a/ojluni/src/main/java/javax/crypto/Mac.java b/ojluni/src/main/java/javax/crypto/Mac.java
index 2315db7..cdf6105 100644
--- a/ojluni/src/main/java/javax/crypto/Mac.java
+++ b/ojluni/src/main/java/javax/crypto/Mac.java
@@ -34,9 +34,6 @@
import java.nio.ByteBuffer;
-/* Android-removed: this debugging mechanism is not used in Android.
-import sun.security.util.Debug;
-*/
import sun.security.jca.*;
import sun.security.jca.GetInstance.Instance;
@@ -156,7 +153,8 @@
public class Mac implements Cloneable {
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -344,7 +342,8 @@
if (spi != null) {
return;
}
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (debug != null) {
int w = --warnCount;
if (w >= 0) {
@@ -472,7 +471,8 @@
}
initialized = true;
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
this.provider.getName());
@@ -501,7 +501,8 @@
}
initialized = true;
- /* Android-removed: this debugging mechanism is not used in Android.
+ // Android-removed: this debugging mechanism is not used in Android.
+ /*
if (!skipDebug && pdebug != null) {
pdebug.println("Mac." + algorithm + " algorithm from: " +
this.provider.getName());
diff --git a/ojluni/src/main/java/jdk/net/package-info.java b/ojluni/src/main/java/jdk/net/package-info.java
deleted file mode 100644
index b05d543..0000000
--- a/ojluni/src/main/java/jdk/net/package-info.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-/**
- * Platform specific socket options for the {@code java.net} and {@code java.nio.channels}
- * socket classes.
- */
-
-@jdk.Exported
-package jdk.net;
diff --git a/ojluni/src/main/java/sun/misc/FDBigInt.java b/ojluni/src/main/java/sun/misc/FDBigInt.java
deleted file mode 100644
index 85b5b35..0000000
--- a/ojluni/src/main/java/sun/misc/FDBigInt.java
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.misc;
-
-/*
- * A really, really simple bigint package
- * tailored to the needs of floating base conversion.
- */
-public class FDBigInt {
- int nWords; // number of words used
- int data[]; // value: data[0] is least significant
-
-
- public FDBigInt( int v ){
- nWords = 1;
- data = new int[1];
- data[0] = v;
- }
-
- public FDBigInt( long v ){
- data = new int[2];
- data[0] = (int)v;
- data[1] = (int)(v>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- }
-
- public FDBigInt( FDBigInt other ){
- data = new int[nWords = other.nWords];
- System.arraycopy( other.data, 0, data, 0, nWords );
- }
-
- private FDBigInt( int [] d, int n ){
- data = d;
- nWords = n;
- }
-
- public FDBigInt( long seed, char digit[], int nd0, int nd ){
- int n= (nd+8)/9; // estimate size needed.
- if ( n < 2 ) n = 2;
- data = new int[n]; // allocate enough space
- data[0] = (int)seed; // starting value
- data[1] = (int)(seed>>>32);
- nWords = (data[1]==0) ? 1 : 2;
- int i = nd0;
- int limit = nd-5; // slurp digits 5 at a time.
- int v;
- while ( i < limit ){
- int ilim = i+5;
- v = (int)digit[i++]-(int)'0';
- while( i <ilim ){
- v = 10*v + (int)digit[i++]-(int)'0';
- }
- multaddMe( 100000, v); // ... where 100000 is 10^5.
- }
- int factor = 1;
- v = 0;
- while ( i < nd ){
- v = 10*v + (int)digit[i++]-(int)'0';
- factor *= 10;
- }
- if ( factor != 1 ){
- multaddMe( factor, v );
- }
- }
-
- /*
- * Left shift by c bits.
- * Shifts this in place.
- */
- public void
- lshiftMe( int c )throws IllegalArgumentException {
- if ( c <= 0 ){
- if ( c == 0 )
- return; // silly.
- else
- throw new IllegalArgumentException("negative shift count");
- }
- int wordcount = c>>5;
- int bitcount = c & 0x1f;
- int anticount = 32-bitcount;
- int t[] = data;
- int s[] = data;
- if ( nWords+wordcount+1 > t.length ){
- // reallocate.
- t = new int[ nWords+wordcount+1 ];
- }
- int target = nWords+wordcount;
- int src = nWords-1;
- if ( bitcount == 0 ){
- // special hack, since an anticount of 32 won't go!
- System.arraycopy( s, 0, t, wordcount, nWords );
- target = wordcount-1;
- } else {
- t[target--] = s[src]>>>anticount;
- while ( src >= 1 ){
- t[target--] = (s[src]<<bitcount) | (s[--src]>>>anticount);
- }
- t[target--] = s[src]<<bitcount;
- }
- while( target >= 0 ){
- t[target--] = 0;
- }
- data = t;
- nWords += wordcount + 1;
- // may have constructed high-order word of 0.
- // if so, trim it
- while ( nWords > 1 && data[nWords-1] == 0 )
- nWords--;
- }
-
- /*
- * normalize this number by shifting until
- * the MSB of the number is at 0x08000000.
- * This is in preparation for quoRemIteration, below.
- * The idea is that, to make division easier, we want the
- * divisor to be "normalized" -- usually this means shifting
- * the MSB into the high words sign bit. But because we know that
- * the quotient will be 0 < q < 10, we would like to arrange that
- * the dividend not span up into another word of precision.
- * (This needs to be explained more clearly!)
- */
- public int
- normalizeMe() throws IllegalArgumentException {
- int src;
- int wordcount = 0;
- int bitcount = 0;
- int v = 0;
- for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){
- wordcount += 1;
- }
- if ( src < 0 ){
- // oops. Value is zero. Cannot normalize it!
- throw new IllegalArgumentException("zero value");
- }
- /*
- * In most cases, we assume that wordcount is zero. This only
- * makes sense, as we try not to maintain any high-order
- * words full of zeros. In fact, if there are zeros, we will
- * simply SHORTEN our number at this point. Watch closely...
- */
- nWords -= wordcount;
- /*
- * Compute how far left we have to shift v s.t. its highest-
- * order bit is in the right place. Then call lshiftMe to
- * do the work.
- */
- if ( (v & 0xf0000000) != 0 ){
- // will have to shift up into the next word.
- // too bad.
- for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- )
- v >>>= 1;
- } else {
- while ( v <= 0x000fffff ){
- // hack: byte-at-a-time shifting
- v <<= 8;
- bitcount += 8;
- }
- while ( v <= 0x07ffffff ){
- v <<= 1;
- bitcount += 1;
- }
- }
- if ( bitcount != 0 )
- lshiftMe( bitcount );
- return bitcount;
- }
-
- /*
- * Multiply a FDBigInt by an int.
- * Result is a new FDBigInt.
- */
- public FDBigInt
- mult( int iv ) {
- long v = iv;
- int r[];
- long p;
-
- // guess adequate size of r.
- r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ];
- p = 0L;
- for( int i=0; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- r[i] = (int)p;
- p >>>= 32;
- }
- if ( p == 0L){
- return new FDBigInt( r, nWords );
- } else {
- r[nWords] = (int)p;
- return new FDBigInt( r, nWords+1 );
- }
- }
-
- /*
- * Multiply a FDBigInt by an int and add another int.
- * Result is computed in place.
- * Hope it fits!
- */
- public void
- multaddMe( int iv, int addend ) {
- long v = iv;
- long p;
-
- // unroll 0th iteration, doing addition.
- p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL);
- data[0] = (int)p;
- p >>>= 32;
- for( int i=1; i < nWords; i++ ) {
- p += v * ((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>>= 32;
- }
- if ( p != 0L){
- data[nWords] = (int)p; // will fail noisily if illegal!
- nWords++;
- }
- }
-
- /*
- * Multiply a FDBigInt by another FDBigInt.
- * Result is a new FDBigInt.
- */
- public FDBigInt
- mult( FDBigInt other ){
- // crudely guess adequate size for r
- int r[] = new int[ nWords + other.nWords ];
- int i;
- // I think I am promised zeros...
-
- for( i = 0; i < this.nWords; i++ ){
- long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION
- long p = 0L;
- int j;
- for( j = 0; j < other.nWords; j++ ){
- p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND.
- r[i+j] = (int)p;
- p >>>= 32;
- }
- r[i+j] = (int)p;
- }
- // compute how much of r we actually needed for all that.
- for ( i = r.length-1; i> 0; i--)
- if ( r[i] != 0 )
- break;
- return new FDBigInt( r, i+1 );
- }
-
- /*
- * Add one FDBigInt to another. Return a FDBigInt
- */
- public FDBigInt
- add( FDBigInt other ){
- int i;
- int a[], b[];
- int n, m;
- long c = 0L;
- // arrange such that a.nWords >= b.nWords;
- // n = a.nWords, m = b.nWords
- if ( this.nWords >= other.nWords ){
- a = this.data;
- n = this.nWords;
- b = other.data;
- m = other.nWords;
- } else {
- a = other.data;
- n = other.nWords;
- b = this.data;
- m = this.nWords;
- }
- int r[] = new int[ n ];
- for ( i = 0; i < n; i++ ){
- c += (long)a[i] & 0xffffffffL;
- if ( i < m ){
- c += (long)b[i] & 0xffffffffL;
- }
- r[i] = (int) c;
- c >>= 32; // signed shift.
- }
- if ( c != 0L ){
- // oops -- carry out -- need longer result.
- int s[] = new int[ r.length+1 ];
- System.arraycopy( r, 0, s, 0, r.length );
- s[i++] = (int)c;
- return new FDBigInt( s, i );
- }
- return new FDBigInt( r, i );
- }
-
- /*
- * Subtract one FDBigInt from another. Return a FDBigInt
- * Assert that the result is positive.
- */
- public FDBigInt
- sub( FDBigInt other ){
- int r[] = new int[ this.nWords ];
- int i;
- int n = this.nWords;
- int m = other.nWords;
- int nzeros = 0;
- long c = 0L;
- for ( i = 0; i < n; i++ ){
- c += (long)this.data[i] & 0xffffffffL;
- if ( i < m ){
- c -= (long)other.data[i] & 0xffffffffL;
- }
- if ( ( r[i] = (int) c ) == 0 )
- nzeros++;
- else
- nzeros = 0;
- c >>= 32; // signed shift
- }
- assert c == 0L : c; // borrow out of subtract
- assert dataInRangeIsZero(i, m, other); // negative result of subtract
- return new FDBigInt( r, n-nzeros );
- }
-
- private static boolean dataInRangeIsZero(int i, int m, FDBigInt other) {
- while ( i < m )
- if (other.data[i++] != 0)
- return false;
- return true;
- }
-
- /*
- * Compare FDBigInt with another FDBigInt. Return an integer
- * >0: this > other
- * 0: this == other
- * <0: this < other
- */
- public int
- cmp( FDBigInt other ){
- int i;
- if ( this.nWords > other.nWords ){
- // if any of my high-order words is non-zero,
- // then the answer is evident
- int j = other.nWords-1;
- for ( i = this.nWords-1; i > j ; i-- )
- if ( this.data[i] != 0 ) return 1;
- }else if ( this.nWords < other.nWords ){
- // if any of other's high-order words is non-zero,
- // then the answer is evident
- int j = this.nWords-1;
- for ( i = other.nWords-1; i > j ; i-- )
- if ( other.data[i] != 0 ) return -1;
- } else{
- i = this.nWords-1;
- }
- for ( ; i > 0 ; i-- )
- if ( this.data[i] != other.data[i] )
- break;
- // careful! want unsigned compare!
- // use brute force here.
- int a = this.data[i];
- int b = other.data[i];
- if ( a < 0 ){
- // a is really big, unsigned
- if ( b < 0 ){
- return a-b; // both big, negative
- } else {
- return 1; // b not big, answer is obvious;
- }
- } else {
- // a is not really big
- if ( b < 0 ) {
- // but b is really big
- return -1;
- } else {
- return a - b;
- }
- }
- }
-
- /*
- * Compute
- * q = (int)( this / S )
- * this = 10 * ( this mod S )
- * Return q.
- * This is the iteration step of digit development for output.
- * We assume that S has been normalized, as above, and that
- * "this" has been lshift'ed accordingly.
- * Also assume, of course, that the result, q, can be expressed
- * as an integer, 0 <= q < 10.
- */
- public int
- quoRemIteration( FDBigInt S )throws IllegalArgumentException {
- // ensure that this and S have the same number of
- // digits. If S is properly normalized and q < 10 then
- // this must be so.
- if ( nWords != S.nWords ){
- throw new IllegalArgumentException("disparate values");
- }
- // estimate q the obvious way. We will usually be
- // right. If not, then we're only off by a little and
- // will re-add.
- int n = nWords-1;
- long q = ((long)data[n]&0xffffffffL) / (long)S.data[n];
- long diff = 0L;
- for ( int i = 0; i <= n ; i++ ){
- diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL);
- data[i] = (int)diff;
- diff >>= 32; // N.B. SIGNED shift.
- }
- if ( diff != 0L ) {
- // damn, damn, damn. q is too big.
- // add S back in until this turns +. This should
- // not be very many times!
- long sum = 0L;
- while ( sum == 0L ){
- sum = 0L;
- for ( int i = 0; i <= n; i++ ){
- sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL);
- data[i] = (int) sum;
- sum >>= 32; // Signed or unsigned, answer is 0 or 1
- }
- /*
- * Originally the following line read
- * "if ( sum !=0 && sum != -1 )"
- * but that would be wrong, because of the
- * treatment of the two values as entirely unsigned,
- * it would be impossible for a carry-out to be interpreted
- * as -1 -- it would have to be a single-bit carry-out, or
- * +1.
- */
- assert sum == 0 || sum == 1 : sum; // carry out of division correction
- q -= 1;
- }
- }
- // finally, we can multiply this by 10.
- // it cannot overflow, right, as the high-order word has
- // at least 4 high-order zeros!
- long p = 0L;
- for ( int i = 0; i <= n; i++ ){
- p += 10*((long)data[i]&0xffffffffL);
- data[i] = (int)p;
- p >>= 32; // SIGNED shift.
- }
- assert p == 0L : p; // Carry out of *10
- return (int)q;
- }
-
- public long
- longValue(){
- // if this can be represented as a long, return the value
- assert this.nWords > 0 : this.nWords; // longValue confused
-
- if (this.nWords == 1)
- return ((long)data[0]&0xffffffffL);
-
- assert dataInRangeIsZero(2, this.nWords, this); // value too big
- assert data[1] >= 0; // value too big
- return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL);
- }
-
- public String
- toString() {
- StringBuffer r = new StringBuffer(30);
- r.append('[');
- int i = Math.min( nWords-1, data.length-1) ;
- if ( nWords > data.length ){
- r.append( "("+data.length+"<"+nWords+"!)" );
- }
- for( ; i> 0 ; i-- ){
- r.append( Integer.toHexString( data[i] ) );
- r.append(' ');
- }
- r.append( Integer.toHexString( data[0] ) );
- r.append(']');
- return new String( r );
- }
-}
diff --git a/ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java b/ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java
index 762df01..3923675 100644
--- a/ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java
+++ b/ojluni/src/main/java/sun/nio/ch/DatagramSocketAdaptor.java
@@ -361,9 +361,7 @@
return dc;
}
- /*
- * Android-added: for testing and internal use.
- */
+ // Android-added: for testing and internal use.
@Override
public final FileDescriptor getFileDescriptor$() {
return dc.fd;
diff --git a/ojluni/src/main/java/sun/nio/ch/SocketAdaptor.java b/ojluni/src/main/java/sun/nio/ch/SocketAdaptor.java
index aa6d834..a2aba2d 100644
--- a/ojluni/src/main/java/sun/nio/ch/SocketAdaptor.java
+++ b/ojluni/src/main/java/sun/nio/ch/SocketAdaptor.java
@@ -453,9 +453,7 @@
return !sc.isOutputOpen();
}
- /*
- * Android-added: for testing and internal use.
- */
+ // Android-added: for testing and internal use.
@Override
public FileDescriptor getFileDescriptor$() {
return sc.getFD();
diff --git a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
index 49d898a..4fa4711 100644
--- a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
+++ b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
@@ -1172,5 +1172,6 @@
}
return tsReply.getEncodedToken();
}
- END Android-removed */
+ */
+ // END Android-removed: unused in Android
}
diff --git a/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java b/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
index b78fdf9..e2f8e28 100644
--- a/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
+++ b/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,21 +33,38 @@
import java.io.OutputStream;
import java.io.IOException;
import java.math.BigInteger;
+import java.security.CryptoPrimitive;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.Timestamp;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
-import java.security.*;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+import sun.misc.HexDumpEncoder;
import sun.security.timestamp.TimestampToken;
-import sun.security.util.*;
+import sun.security.util.Debug;
+import sun.security.util.DerEncoder;
+import sun.security.util.DerInputStream;
+import sun.security.util.DerOutputStream;
+import sun.security.util.DerValue;
+import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
import sun.security.x509.KeyUsageExtension;
import sun.security.x509.PKIXExtensions;
-import sun.misc.HexDumpEncoder;
/**
* A SignerInfo, as defined in PKCS#7's signedData type.
@@ -56,6 +73,17 @@
*/
public class SignerInfo implements DerEncoder {
+ // Digest and Signature restrictions
+ private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET =
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+
+ private static final Set<CryptoPrimitive> SIG_PRIMITIVE_SET =
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.SIGNATURE));
+
+ private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
BigInteger version;
X500Name issuerName;
BigInteger certificateSerialNumber;
@@ -337,6 +365,13 @@
if (messageDigest == null) // fail if there is no message digest
return null;
+ // check that algorithm is not restricted
+ if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET,
+ digestAlgname, null)) {
+ throw new SignatureException("Digest check failed. " +
+ "Disabled algorithm used: " + digestAlgname);
+ }
+
MessageDigest md = MessageDigest.getInstance(digestAlgname);
byte[] buffer = new byte[4096];
@@ -374,12 +409,24 @@
String algname = AlgorithmId.makeSigAlg(
digestAlgname, encryptionAlgname);
- Signature sig = Signature.getInstance(algname);
- X509Certificate cert = getCertificate(block);
+ // check that algorithm is not restricted
+ if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, algname, null)) {
+ throw new SignatureException("Signature check failed. " +
+ "Disabled algorithm used: " + algname);
+ }
+ X509Certificate cert = getCertificate(block);
+ PublicKey key = cert.getPublicKey();
if (cert == null) {
return null;
}
+
+ // check if the public key is restricted
+ if (!JAR_DISABLED_CHECK.permits(SIG_PRIMITIVE_SET, key)) {
+ throw new SignatureException("Public key check failed. " +
+ "Disabled algorithm used: " + key.getAlgorithm());
+ }
+
if (cert.hasUnsupportedCriticalExtension()) {
throw new SignatureException("Certificate has unsupported "
+ "critical extension(s)");
@@ -416,7 +463,7 @@
}
}
- PublicKey key = cert.getPublicKey();
+ Signature sig = Signature.getInstance(algname);
sig.initVerify(key);
byte[] buffer = new byte[4096];
@@ -549,9 +596,16 @@
*/
private void verifyTimestamp(TimestampToken token)
throws NoSuchAlgorithmException, SignatureException {
+ String digestAlgname = token.getHashAlgorithm().getName();
+ // check that algorithm is not restricted
+ if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, digestAlgname,
+ null)) {
+ throw new SignatureException("Timestamp token digest check failed. " +
+ "Disabled algorithm used: " + digestAlgname);
+ }
MessageDigest md =
- MessageDigest.getInstance(token.getHashAlgorithm().getName());
+ MessageDigest.getInstance(digestAlgname);
if (!Arrays.equals(token.getHashedMessage(),
md.digest(encryptedDigest))) {
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/AlgorithmChecker.java b/ojluni/src/main/java/sun/security/provider/certpath/AlgorithmChecker.java
index e92590a..f727a3a 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/AlgorithmChecker.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/AlgorithmChecker.java
@@ -255,16 +255,17 @@
PublicKey currPubKey = cert.getPublicKey();
- // Check against DisabledAlgorithmConstraints certpath constraints.
- // permits() will throw exception on failure.
- certPathDefaultConstraints.permits(primitives,
+ if (constraints instanceof DisabledAlgorithmConstraints) {
+ // Check against DisabledAlgorithmConstraints certpath constraints.
+ // permits() will throw exception on failure.
+ ((DisabledAlgorithmConstraints)constraints).permits(primitives,
new CertConstraintParameters((X509Certificate)cert,
trustedMatch));
- // new CertConstraintParameters(x509Cert, trustedMatch));
- // If there is no previous key, set one and exit
- if (prevPubKey == null) {
- prevPubKey = currPubKey;
- return;
+ // If there is no previous key, set one and exit
+ if (prevPubKey == null) {
+ prevPubKey = currPubKey;
+ return;
+ }
}
X509CertImpl x509Cert;
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/Builder.java b/ojluni/src/main/java/sun/security/provider/certpath/Builder.java
index 84cbe66..e6b5fc0 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/Builder.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/Builder.java
@@ -102,8 +102,8 @@
/**
* Verifies whether the input certificate completes the path.
- * When building forward, a trust anchor will complete the path.
- * When building reverse, the target certificate will complete the path.
+ * When building in the forward direction, a trust anchor will
+ * complete the path.
*
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/ForwardBuilder.java b/ojluni/src/main/java/sun/security/provider/certpath/ForwardBuilder.java
index 57e819c..27bb25f 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/ForwardBuilder.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/ForwardBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -824,18 +824,19 @@
/**
* Verifies whether the input certificate completes the path.
- * Checks the cert against each trust anchor that was specified, in order,
- * and returns true as soon as it finds a valid anchor.
- * Returns true if the cert matches a trust anchor specified as a
- * certificate or if the cert verifies with a trust anchor that
- * was specified as a trusted {pubkey, caname} pair. Returns false if none
- * of the trust anchors are valid for this cert.
- *
- * @param cert the certificate to test
- * @return a boolean value indicating whether the cert completes the path.
+ * First checks the cert against each trust anchor that was specified,
+ * in order, and returns true if the cert matches the trust anchor
+ * specified as a certificate or has the same key and subject of an anchor
+ * specified as a trusted {pubkey, caname} pair.
+ * If no match has been found, does a second check of the cert against
+ * anchors specified as a trusted {pubkey, caname} pair to see if the cert
+ * was issued by that anchor.
+ * Returns false if none of the trust anchors are valid for this cert.
*/
@Override
boolean isPathCompleted(X509Certificate cert) {
+ List<TrustAnchor> otherAnchors = new ArrayList<>();
+ // first, check if cert is already trusted
for (TrustAnchor anchor : trustAnchors) {
if (anchor.getTrustedCert() != null) {
if (cert.equals(anchor.getTrustedCert())) {
@@ -857,7 +858,12 @@
}
// else, it is a self-issued certificate of the anchor
}
-
+ otherAnchors.add(anchor);
+ }
+ // next, check if cert is issued by anchor specified by key/name
+ for (TrustAnchor anchor : otherAnchors) {
+ X500Principal principal = anchor.getCA();
+ PublicKey publicKey = anchor.getCAPublicKey();
// Check subject/issuer name chaining
if (principal == null ||
!principal.equals(cert.getIssuerX500Principal())) {
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/OCSPResponse.java b/ojluni/src/main/java/sun/security/provider/certpath/OCSPResponse.java
index 8075d73..c8a75ea 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/OCSPResponse.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/OCSPResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -151,8 +151,8 @@
private static final int DEFAULT_MAX_CLOCK_SKEW = 900000;
/**
- * Integer value indicating the maximum allowable clock skew, in seconds,
- * to be used for the OCSP check.
+ * Integer value indicating the maximum allowable clock skew,
+ * in milliseconds, to be used for the OCSP check.
*/
private static final int MAX_CLOCK_SKEW = initializeClockSkew();
@@ -586,13 +586,14 @@
"Unable to verify OCSP Response's signature");
}
- // Check freshness of OCSPResponse
if (nonce != null) {
if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) {
throw new CertPathValidatorException("Nonces don't match");
}
}
+ // Check freshness of OCSPResponse
+
long now = (date == null) ? System.currentTimeMillis() : date.getTime();
Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
@@ -602,13 +603,18 @@
if (sr.nextUpdate != null) {
until = " until " + sr.nextUpdate;
}
- debug.println("Response's validity interval is from " +
- sr.thisUpdate + until);
+ debug.println("OCSP response validity interval is from " +
+ sr.thisUpdate + until);
+ debug.println("Checking validity of OCSP response on: " +
+ new Date(now));
}
- // Check that the test date is within the validity interval
- if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) ||
- (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate)))
+ // Check that the test date is within the validity interval:
+ // [ thisUpdate - MAX_CLOCK_SKEW,
+ // MAX(thisUpdate, nextUpdate) + MAX_CLOCK_SKEW ]
+ if (nowPlusSkew.before(sr.thisUpdate) ||
+ nowMinusSkew.after(
+ sr.nextUpdate != null ? sr.nextUpdate : sr.thisUpdate))
{
throw new CertPathValidatorException(
"Response is unreliable: its validity " +
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/PKIX.java b/ojluni/src/main/java/sun/security/provider/certpath/PKIX.java
index 98c8834..e33d4a2 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/PKIX.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/PKIX.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,6 @@
package sun.security.provider.certpath;
import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyStore;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.interfaces.DSAPublicKey;
@@ -194,7 +193,6 @@
static class BuilderParams extends ValidatorParams {
private PKIXBuilderParameters params;
- private boolean buildForward = true;
private List<CertStore> stores;
private X500Principal targetSubject;
@@ -213,10 +211,6 @@
+ "targetCertConstraints parameter must be an "
+ "X509CertSelector");
}
- if (params instanceof SunCertPathBuilderParameters) {
- buildForward =
- ((SunCertPathBuilderParameters)params).getBuildForward();
- }
this.params = params;
this.targetSubject = getTargetSubject(
certStores(), (X509CertSelector)targetCertConstraints());
@@ -230,7 +224,6 @@
return stores;
}
int maxPathLength() { return params.getMaxPathLength(); }
- boolean buildForward() { return buildForward; }
PKIXBuilderParameters params() { return params; }
X500Principal targetSubject() { return targetSubject; }
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java b/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java
index 492e851..d2d9e36 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -94,9 +94,6 @@
X509Certificate firstCert = certList.get(0);
// check trusted certificate's subject
selector.setSubject(firstCert.getIssuerX500Principal());
- // check the validity period
- selector.setValidityPeriod(firstCert.getNotBefore(),
- firstCert.getNotAfter());
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
@@ -162,13 +159,22 @@
ValidatorParams params)
throws CertPathValidatorException
{
+ // add standard checkers that we will be using
+ // Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
+ // check if anchor is untrusted
+ //UntrustedChecker untrustedChecker = new UntrustedChecker();
+ //X509Certificate anchorCert = anchor.getTrustedCert();
+ //if (anchorCert != null) {
+ // untrustedChecker.check(anchorCert);
+ //}
+
int certPathLen = params.certificates().size();
// create PKIXCertPathCheckers
List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
// add standard checkers that we will be using
// Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
- // certPathCheckers.add(new UntrustedChecker());
+ // certPathCheckers.add(untrustedChecker);
certPathCheckers.add(new AlgorithmChecker(anchor));
certPathCheckers.add(new KeyChecker(certPathLen,
params.targetCertConstraints()));
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/ReverseBuilder.java b/ojluni/src/main/java/sun/security/provider/certpath/ReverseBuilder.java
deleted file mode 100644
index 1815a22..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/ReverseBuilder.java
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath;
-
-import java.io.IOException;
-import java.security.GeneralSecurityException;
-import java.security.Principal;
-import java.security.cert.CertificateException;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertStore;
-import java.security.cert.CertStoreException;
-import java.security.cert.PKIXBuilderParameters;
-import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.PKIXParameters;
-import java.security.cert.PKIXReason;
-import java.security.cert.TrustAnchor;
-import java.security.cert.X509Certificate;
-import java.security.cert.X509CertSelector;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.Set;
-
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.provider.certpath.PKIX.BuilderParams;
-import sun.security.util.Debug;
-import sun.security.x509.Extension;
-import static sun.security.x509.PKIXExtensions.*;
-import sun.security.x509.X500Name;
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.PolicyMappingsExtension;
-
-/**
- * This class represents a reverse builder, which is able to retrieve
- * matching certificates from CertStores and verify a particular certificate
- * against a ReverseState.
- *
- * @since 1.4
- * @author Sean Mullan
- * @author Yassir Elley
- */
-
-class ReverseBuilder extends Builder {
-
- private Debug debug = Debug.getInstance("certpath");
-
- private final Set<String> initPolicies;
-
- /**
- * Initialize the builder with the input parameters.
- *
- * @param params the parameter set used to build a certification path
- */
- ReverseBuilder(BuilderParams buildParams) {
- super(buildParams);
-
- Set<String> initialPolicies = buildParams.initialPolicies();
- initPolicies = new HashSet<String>();
- if (initialPolicies.isEmpty()) {
- // if no initialPolicies are specified by user, set
- // initPolicies to be anyPolicy by default
- initPolicies.add(PolicyChecker.ANY_POLICY);
- } else {
- initPolicies.addAll(initialPolicies);
- }
- }
-
- /**
- * Retrieves all certs from the specified CertStores that satisfy the
- * requirements specified in the parameters and the current
- * PKIX state (name constraints, policy constraints, etc).
- *
- * @param currentState the current state.
- * Must be an instance of <code>ReverseState</code>
- * @param certStores list of CertStores
- */
- @Override
- Collection<X509Certificate> getMatchingCerts
- (State currState, List<CertStore> certStores)
- throws CertStoreException, CertificateException, IOException
- {
- ReverseState currentState = (ReverseState) currState;
-
- if (debug != null)
- debug.println("In ReverseBuilder.getMatchingCerts.");
-
- /*
- * The last certificate could be an EE or a CA certificate
- * (we may be building a partial certification path or
- * establishing trust in a CA).
- *
- * Try the EE certs before the CA certs. It will be more
- * common to build a path to an end entity.
- */
- Collection<X509Certificate> certs =
- getMatchingEECerts(currentState, certStores);
- certs.addAll(getMatchingCACerts(currentState, certStores));
-
- return certs;
- }
-
- /*
- * Retrieves all end-entity certificates which satisfy constraints
- * and requirements specified in the parameters and PKIX state.
- */
- private Collection<X509Certificate> getMatchingEECerts
- (ReverseState currentState, List<CertStore> certStores)
- throws CertStoreException, CertificateException, IOException {
-
- /*
- * Compose a CertSelector to filter out
- * certs which do not satisfy requirements.
- *
- * First, retrieve clone of current target cert constraints, and
- * then add more selection criteria based on current validation state.
- */
- X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
-
- /*
- * Match on issuer (subject of previous cert)
- */
- sel.setIssuer(currentState.subjectDN);
-
- /*
- * Match on certificate validity date.
- */
- sel.setCertificateValid(buildParams.date());
-
- /*
- * Policy processing optimizations
- */
- if (currentState.explicitPolicy == 0)
- sel.setPolicy(getMatchingPolicies());
-
- /*
- * If previous cert has a subject key identifier extension,
- * use it to match on authority key identifier extension.
- */
- /*if (currentState.subjKeyId != null) {
- AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
- (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
- null, null);
- sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
- }*/
-
- /*
- * Require EE certs
- */
- sel.setBasicConstraints(-2);
-
- /* Retrieve matching certs from CertStores */
- HashSet<X509Certificate> eeCerts = new HashSet<>();
- addMatchingCerts(sel, certStores, eeCerts, true);
-
- if (debug != null) {
- debug.println("ReverseBuilder.getMatchingEECerts got "
- + eeCerts.size() + " certs.");
- }
- return eeCerts;
- }
-
- /*
- * Retrieves all CA certificates which satisfy constraints
- * and requirements specified in the parameters and PKIX state.
- */
- private Collection<X509Certificate> getMatchingCACerts
- (ReverseState currentState, List<CertStore> certStores)
- throws CertificateException, CertStoreException, IOException {
-
- /*
- * Compose a CertSelector to filter out
- * certs which do not satisfy requirements.
- */
- X509CertSelector sel = new X509CertSelector();
-
- /*
- * Match on issuer (subject of previous cert)
- */
- sel.setIssuer(currentState.subjectDN);
-
- /*
- * Match on certificate validity date.
- */
- sel.setCertificateValid(buildParams.date());
-
- /*
- * Match on target subject name (checks that current cert's
- * name constraints permit it to certify target).
- * (4 is the integer type for DIRECTORY name).
- */
- byte[] subject = targetCertConstraints.getSubjectAsBytes();
- if (subject != null) {
- sel.addPathToName(4, subject);
- } else {
- X509Certificate cert = targetCertConstraints.getCertificate();
- if (cert != null) {
- sel.addPathToName(4,
- cert.getSubjectX500Principal().getEncoded());
- }
- }
-
- /*
- * Policy processing optimizations
- */
- if (currentState.explicitPolicy == 0)
- sel.setPolicy(getMatchingPolicies());
-
- /*
- * If previous cert has a subject key identifier extension,
- * use it to match on authority key identifier extension.
- */
- /*if (currentState.subjKeyId != null) {
- AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
- (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
- null, null);
- sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
- }*/
-
- /*
- * Require CA certs
- */
- sel.setBasicConstraints(0);
-
- /* Retrieve matching certs from CertStores */
- ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
- addMatchingCerts(sel, certStores, reverseCerts, true);
-
- /* Sort remaining certs using name constraints */
- Collections.sort(reverseCerts, new PKIXCertComparator());
-
- if (debug != null)
- debug.println("ReverseBuilder.getMatchingCACerts got " +
- reverseCerts.size() + " certs.");
- return reverseCerts;
- }
-
- /*
- * This inner class compares 2 PKIX certificates according to which
- * should be tried first when building a path to the target. For
- * now, the algorithm is to look at name constraints in each cert and those
- * which constrain the path closer to the target should be
- * ranked higher. Later, we may want to consider other components,
- * such as key identifiers.
- */
- class PKIXCertComparator implements Comparator<X509Certificate> {
-
- private Debug debug = Debug.getInstance("certpath");
-
- @Override
- public int compare(X509Certificate cert1, X509Certificate cert2) {
-
- /*
- * if either cert certifies the target, always
- * put at head of list.
- */
- X500Principal targetSubject = buildParams.targetSubject();
- if (cert1.getSubjectX500Principal().equals(targetSubject)) {
- return -1;
- }
- if (cert2.getSubjectX500Principal().equals(targetSubject)) {
- return 1;
- }
-
- int targetDist1;
- int targetDist2;
- try {
- X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
- targetDist1 = Builder.targetDistance(
- null, cert1, targetSubjectName);
- targetDist2 = Builder.targetDistance(
- null, cert2, targetSubjectName);
- } catch (IOException e) {
- if (debug != null) {
- debug.println("IOException in call to Builder.targetDistance");
- e.printStackTrace();
- }
- throw new ClassCastException
- ("Invalid target subject distinguished name");
- }
-
- if (targetDist1 == targetDist2)
- return 0;
-
- if (targetDist1 == -1)
- return 1;
-
- if (targetDist1 < targetDist2)
- return -1;
-
- return 1;
- }
- }
-
- /**
- * Verifies a matching certificate.
- *
- * This method executes any of the validation steps in the PKIX path validation
- * algorithm which were not satisfied via filtering out non-compliant
- * certificates with certificate matching rules.
- *
- * If the last certificate is being verified (the one whose subject
- * matches the target subject, then the steps in Section 6.1.4 of the
- * Certification Path Validation algorithm are NOT executed,
- * regardless of whether or not the last cert is an end-entity
- * cert or not. This allows callers to certify CA certs as
- * well as EE certs.
- *
- * @param cert the certificate to be verified
- * @param currentState the current state against which the cert is verified
- * @param certPathList the certPathList generated thus far
- */
- @Override
- void verifyCert(X509Certificate cert, State currState,
- List<X509Certificate> certPathList)
- throws GeneralSecurityException
- {
- if (debug != null) {
- debug.println("ReverseBuilder.verifyCert(SN: "
- + Debug.toHexString(cert.getSerialNumber())
- + "\n Subject: " + cert.getSubjectX500Principal() + ")");
- }
-
- ReverseState currentState = (ReverseState) currState;
-
- /* we don't perform any validation of the trusted cert */
- if (currentState.isInitial()) {
- return;
- }
-
- // BEGIN Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
- // // Don't bother to verify untrusted certificate more.
- // currentState.untrustedChecker.check(cert,
- // Collections.<String>emptySet());
- // END Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
-
- /*
- * check for looping - abort a loop if
- * ((we encounter the same certificate twice) AND
- * ((policyMappingInhibited = true) OR (no policy mapping
- * extensions can be found between the occurrences of the same
- * certificate)))
- * in order to facilitate the check to see if there are
- * any policy mapping extensions found between the occurrences
- * of the same certificate, we reverse the certpathlist first
- */
- if ((certPathList != null) && (!certPathList.isEmpty())) {
- List<X509Certificate> reverseCertList = new ArrayList<>();
- for (X509Certificate c : certPathList) {
- reverseCertList.add(0, c);
- }
-
- boolean policyMappingFound = false;
- for (X509Certificate cpListCert : reverseCertList) {
- X509CertImpl cpListCertImpl = X509CertImpl.toImpl(cpListCert);
- PolicyMappingsExtension policyMappingsExt =
- cpListCertImpl.getPolicyMappingsExtension();
- if (policyMappingsExt != null) {
- policyMappingFound = true;
- }
- if (debug != null)
- debug.println("policyMappingFound = " + policyMappingFound);
- if (cert.equals(cpListCert)) {
- if ((buildParams.policyMappingInhibited()) ||
- (!policyMappingFound)){
- if (debug != null)
- debug.println("loop detected!!");
- throw new CertPathValidatorException("loop detected");
- }
- }
- }
- }
-
- /* check if target cert */
- boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
-
- /* check if CA cert */
- boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
-
- /* if there are more certs to follow, verify certain constraints */
- if (!finalCert) {
-
- /* check if CA cert */
- if (!caCert)
- throw new CertPathValidatorException("cert is NOT a CA cert");
-
- /* If the certificate was not self-issued, verify that
- * remainingCerts is greater than zero
- */
- if ((currentState.remainingCACerts <= 0) && !X509CertImpl.isSelfIssued(cert)) {
- throw new CertPathValidatorException
- ("pathLenConstraint violated, path too long", null,
- null, -1, PKIXReason.PATH_TOO_LONG);
- }
-
- /*
- * Check keyUsage extension (only if CA cert and not final cert)
- */
- KeyChecker.verifyCAKeyUsage(cert);
-
- } else {
-
- /*
- * If final cert, check that it satisfies specified target
- * constraints
- */
- if (targetCertConstraints.match(cert) == false) {
- throw new CertPathValidatorException("target certificate " +
- "constraints check failed");
- }
- }
-
- /*
- * Check revocation.
- */
- if (buildParams.revocationEnabled() && currentState.revChecker != null) {
- currentState.revChecker.check(cert, Collections.<String>emptySet());
- }
-
- /* Check name constraints if this is not a self-issued cert */
- if (finalCert || !X509CertImpl.isSelfIssued(cert)){
- if (currentState.nc != null) {
- try {
- if (!currentState.nc.verify(cert)){
- throw new CertPathValidatorException
- ("name constraints check failed", null, null, -1,
- PKIXReason.INVALID_NAME);
- }
- } catch (IOException ioe) {
- throw new CertPathValidatorException(ioe);
- }
- }
- }
-
- /*
- * Check policy
- */
- X509CertImpl certImpl = X509CertImpl.toImpl(cert);
- currentState.rootNode = PolicyChecker.processPolicies
- (currentState.certIndex, initPolicies,
- currentState.explicitPolicy, currentState.policyMapping,
- currentState.inhibitAnyPolicy,
- buildParams.policyQualifiersRejected(), currentState.rootNode,
- certImpl, finalCert);
-
- /*
- * Check CRITICAL private extensions
- */
- Set<String> unresolvedCritExts = cert.getCriticalExtensionOIDs();
- if (unresolvedCritExts == null) {
- unresolvedCritExts = Collections.<String>emptySet();
- }
-
- /*
- * Check that the signature algorithm is not disabled.
- */
- currentState.algorithmChecker.check(cert, unresolvedCritExts);
-
- for (PKIXCertPathChecker checker : currentState.userCheckers) {
- checker.check(cert, unresolvedCritExts);
- }
-
- /*
- * Look at the remaining extensions and remove any ones we have
- * already checked. If there are any left, throw an exception!
- */
- if (!unresolvedCritExts.isEmpty()) {
- unresolvedCritExts.remove(BasicConstraints_Id.toString());
- unresolvedCritExts.remove(NameConstraints_Id.toString());
- unresolvedCritExts.remove(CertificatePolicies_Id.toString());
- unresolvedCritExts.remove(PolicyMappings_Id.toString());
- unresolvedCritExts.remove(PolicyConstraints_Id.toString());
- unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
- unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
- unresolvedCritExts.remove(KeyUsage_Id.toString());
- unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
-
- if (!unresolvedCritExts.isEmpty())
- throw new CertPathValidatorException
- ("Unrecognized critical extension(s)", null, null, -1,
- PKIXReason.UNRECOGNIZED_CRIT_EXT);
- }
-
- /*
- * Check signature.
- */
- if (buildParams.sigProvider() != null) {
- cert.verify(currentState.pubKey, buildParams.sigProvider());
- } else {
- cert.verify(currentState.pubKey);
- }
- }
-
- /**
- * Verifies whether the input certificate completes the path.
- * This checks whether the cert is the target certificate.
- *
- * @param cert the certificate to test
- * @return a boolean value indicating whether the cert completes the path.
- */
- @Override
- boolean isPathCompleted(X509Certificate cert) {
- return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
- }
-
- /** Adds the certificate to the certPathList
- *
- * @param cert the certificate to be added
- * @param certPathList the certification path list
- */
- @Override
- void addCertToPath(X509Certificate cert,
- LinkedList<X509Certificate> certPathList) {
- certPathList.addLast(cert);
- }
-
- /** Removes final certificate from the certPathList
- *
- * @param certPathList the certification path list
- */
- @Override
- void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
- certPathList.removeLast();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/ReverseState.java b/ojluni/src/main/java/sun/security/provider/certpath/ReverseState.java
deleted file mode 100644
index a9944af..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/ReverseState.java
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath;
-
-import java.io.IOException;
-import java.security.PublicKey;
-import java.security.cert.CertificateException;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.PKIXRevocationChecker;
-import java.security.cert.TrustAnchor;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Set;
-import javax.security.auth.x500.X500Principal;
-
-import sun.security.provider.certpath.PKIX.BuilderParams;
-import sun.security.util.Debug;
-import sun.security.x509.NameConstraintsExtension;
-import sun.security.x509.SubjectKeyIdentifierExtension;
-import sun.security.x509.X509CertImpl;
-
-/**
- * A specification of a reverse PKIX validation state
- * which is initialized by each build and updated each time a
- * certificate is added to the current path.
- * @since 1.4
- * @author Sean Mullan
- * @author Yassir Elley
- */
-
-class ReverseState implements State {
-
- private static final Debug debug = Debug.getInstance("certpath");
-
- /* The subject DN of the last cert in the path */
- X500Principal subjectDN;
-
- /* The subject public key of the last cert */
- PublicKey pubKey;
-
- /* The subject key identifier extension (if any) of the last cert */
- SubjectKeyIdentifierExtension subjKeyId;
-
- /* The PKIX constrained/excluded subtrees state variable */
- NameConstraintsExtension nc;
-
- /* The PKIX explicit policy, policy mapping, and inhibit_any-policy
- state variables */
- int explicitPolicy;
- int policyMapping;
- int inhibitAnyPolicy;
- int certIndex;
- PolicyNodeImpl rootNode;
-
- /* The number of remaining CA certs which may follow in the path.
- * -1: previous cert was an EE cert
- * 0: only EE certs may follow.
- * >0 and <Integer.MAX_VALUE:no more than this number of CA certs may follow
- * Integer.MAX_VALUE: unlimited
- */
- int remainingCACerts;
-
- /* The list of user-defined checkers retrieved from the PKIXParameters
- * instance */
- ArrayList<PKIXCertPathChecker> userCheckers;
-
- /* Flag indicating if state is initial (path is just starting) */
- private boolean init = true;
-
- /* the checker used for revocation status */
- RevocationChecker revChecker;
-
- /* the algorithm checker */
- AlgorithmChecker algorithmChecker;
-
- /* the untrusted certificates checker */
- // Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
- // UntrustedChecker untrustedChecker;
-
- /* the trust anchor used to validate the path */
- TrustAnchor trustAnchor;
-
- /* Flag indicating if current cert can vouch for the CRL for
- * the next cert
- */
- boolean crlSign = true;
-
- /**
- * Returns a boolean flag indicating if the state is initial
- * (just starting)
- *
- * @return boolean flag indicating if the state is initial (just starting)
- */
- @Override
- public boolean isInitial() {
- return init;
- }
-
- /**
- * Display state for debugging purposes
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("State [");
- sb.append("\n subjectDN of last cert: ").append(subjectDN);
- sb.append("\n subjectKeyIdentifier: ").append
- (String.valueOf(subjKeyId));
- sb.append("\n nameConstraints: ").append(String.valueOf(nc));
- sb.append("\n certIndex: ").append(certIndex);
- sb.append("\n explicitPolicy: ").append(explicitPolicy);
- sb.append("\n policyMapping: ").append(policyMapping);
- sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy);
- sb.append("\n rootNode: ").append(rootNode);
- sb.append("\n remainingCACerts: ").append(remainingCACerts);
- sb.append("\n crlSign: ").append(crlSign);
- sb.append("\n init: ").append(init);
- sb.append("\n]\n");
- return sb.toString();
- }
-
- /**
- * Initialize the state.
- *
- * @param buildParams builder parameters
- */
- public void initState(BuilderParams buildParams)
- throws CertPathValidatorException
- {
- /*
- * Initialize number of remainingCACerts.
- * Note that -1 maxPathLen implies unlimited.
- * 0 implies only an EE cert is acceptable.
- */
- int maxPathLen = buildParams.maxPathLength();
- remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE
- : maxPathLen;
-
- /* Initialize explicit policy state variable */
- if (buildParams.explicitPolicyRequired()) {
- explicitPolicy = 0;
- } else {
- // unconstrained if maxPathLen is -1,
- // otherwise, we want to initialize this to the value of the
- // longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
- explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
- }
-
- /* Initialize policy mapping state variable */
- if (buildParams.policyMappingInhibited()) {
- policyMapping = 0;
- } else {
- policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
- }
-
- /* Initialize inhibit any policy state variable */
- if (buildParams.anyPolicyInhibited()) {
- inhibitAnyPolicy = 0;
- } else {
- inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
- }
-
- /* Initialize certIndex */
- certIndex = 1;
-
- /* Initialize policy tree */
- Set<String> initExpPolSet = new HashSet<>(1);
- initExpPolSet.add(PolicyChecker.ANY_POLICY);
-
- rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
- false, initExpPolSet, false);
-
- /*
- * Initialize each user-defined checker
- * Shallow copy the checkers
- */
- userCheckers = new ArrayList<>(buildParams.certPathCheckers());
- /* initialize each checker (just in case) */
- for (PKIXCertPathChecker checker : userCheckers) {
- checker.init(false);
- }
-
- /* Start by trusting the cert to sign CRLs */
- crlSign = true;
-
- init = true;
- }
-
- /**
- * Update the state with the specified trust anchor.
- *
- * @param anchor the most-trusted CA
- * @param buildParams builder parameters
- */
- public void updateState(TrustAnchor anchor, BuilderParams buildParams)
- throws CertificateException, IOException, CertPathValidatorException
- {
- trustAnchor = anchor;
- X509Certificate trustedCert = anchor.getTrustedCert();
- if (trustedCert != null) {
- updateState(trustedCert);
- } else {
- X500Principal caName = anchor.getCA();
- updateState(anchor.getCAPublicKey(), caName);
- }
-
- // The user specified AlgorithmChecker and RevocationChecker may not be
- // able to set the trust anchor until now.
- boolean revCheckerAdded = false;
- for (PKIXCertPathChecker checker : userCheckers) {
- if (checker instanceof AlgorithmChecker) {
- ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
- } else if (checker instanceof PKIXRevocationChecker) {
- if (revCheckerAdded) {
- throw new CertPathValidatorException(
- "Only one PKIXRevocationChecker can be specified");
- }
- // if it's our own, initialize it
- if (checker instanceof RevocationChecker) {
- ((RevocationChecker)checker).init(anchor, buildParams);
- }
- ((PKIXRevocationChecker)checker).init(false);
- revCheckerAdded = true;
- }
- }
-
- // only create a RevocationChecker if revocation is enabled and
- // a PKIXRevocationChecker has not already been added
- if (buildParams.revocationEnabled() && !revCheckerAdded) {
- revChecker = new RevocationChecker(anchor, buildParams);
- revChecker.init(false);
- }
-
- init = false;
- }
-
- /**
- * Update the state. This method is used when the most-trusted CA is
- * a trusted public-key and caName, instead of a trusted cert.
- *
- * @param pubKey the public key of the trusted CA
- * @param subjectDN the subject distinguished name of the trusted CA
- */
- private void updateState(PublicKey pubKey, X500Principal subjectDN) {
-
- /* update subject DN */
- this.subjectDN = subjectDN;
-
- /* update subject public key */
- this.pubKey = pubKey;
- }
-
- /**
- * Update the state with the next certificate added to the path.
- *
- * @param cert the certificate which is used to update the state
- */
- public void updateState(X509Certificate cert)
- throws CertificateException, IOException, CertPathValidatorException {
-
- if (cert == null) {
- return;
- }
-
- /* update subject DN */
- subjectDN = cert.getSubjectX500Principal();
-
- /* check for key needing to inherit alg parameters */
- X509CertImpl icert = X509CertImpl.toImpl(cert);
- PublicKey newKey = cert.getPublicKey();
- if (PKIX.isDSAPublicKeyWithoutParams(newKey)) {
- newKey = BasicChecker.makeInheritedParamsKey(newKey, pubKey);
- }
-
- /* update subject public key */
- pubKey = newKey;
-
- /*
- * if this is a trusted cert (init == true), then we
- * don't update any of the remaining fields
- */
- if (init) {
- init = false;
- return;
- }
-
- /* update subject key identifier */
- subjKeyId = icert.getSubjectKeyIdentifierExtension();
-
- /* update crlSign */
- crlSign = RevocationChecker.certCanSignCrl(cert);
-
- /* update current name constraints */
- if (nc != null) {
- nc.merge(icert.getNameConstraintsExtension());
- } else {
- nc = icert.getNameConstraintsExtension();
- if (nc != null) {
- // Make sure we do a clone here, because we're probably
- // going to modify this object later and we don't want to
- // be sharing it with a Certificate object!
- nc = (NameConstraintsExtension) nc.clone();
- }
- }
-
- /* update policy state variables */
- explicitPolicy =
- PolicyChecker.mergeExplicitPolicy(explicitPolicy, icert, false);
- policyMapping =
- PolicyChecker.mergePolicyMapping(policyMapping, icert);
- inhibitAnyPolicy =
- PolicyChecker.mergeInhibitAnyPolicy(inhibitAnyPolicy, icert);
- certIndex++;
-
- /*
- * Update remaining CA certs
- */
- remainingCACerts =
- ConstraintsChecker.mergeBasicConstraints(cert, remainingCACerts);
-
- init = false;
- }
-
- /**
- * Returns a boolean flag indicating if a key lacking necessary key
- * algorithm parameters has been encountered.
- *
- * @return boolean flag indicating if key lacking parameters encountered.
- */
- @Override
- public boolean keyParamsNeeded() {
- /* when building in reverse, we immediately get parameters needed
- * or else throw an exception
- */
- return false;
- }
-
- /*
- * Clone current state. The state is cloned as each cert is
- * added to the path. This is necessary if backtracking occurs,
- * and a prior state needs to be restored.
- *
- * Note that this is a SMART clone. Not all fields are fully copied,
- * because some of them (e.g., subjKeyId) will
- * not have their contents modified by subsequent calls to updateState.
- */
- @Override
- @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
- public Object clone() {
- try {
- ReverseState clonedState = (ReverseState) super.clone();
-
- /* clone checkers, if cloneable */
- clonedState.userCheckers =
- (ArrayList<PKIXCertPathChecker>)userCheckers.clone();
- ListIterator<PKIXCertPathChecker> li =
- clonedState.userCheckers.listIterator();
- while (li.hasNext()) {
- PKIXCertPathChecker checker = li.next();
- if (checker instanceof Cloneable) {
- li.set((PKIXCertPathChecker)checker.clone());
- }
- }
-
- /* make copy of name constraints */
- if (nc != null) {
- clonedState.nc = (NameConstraintsExtension) nc.clone();
- }
-
- /* make copy of policy tree */
- if (rootNode != null) {
- clonedState.rootNode = rootNode.copyTree();
- }
-
- return clonedState;
- } catch (CloneNotSupportedException e) {
- throw new InternalError(e.toString(), e);
- }
- }
-}
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java b/ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java
index 61d5fd7..7445ade 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java
@@ -1041,20 +1041,17 @@
boolean signFlag = true;
List<? extends Certificate> cpList =
cpbr.getCertPath().getCertificates();
- if (cpList.isEmpty()) {
- return;
- }
try {
- for (int i = cpList.size()-1; i >= 0; i-- ) {
- X509Certificate cert = (X509Certificate)cpList.get(i);
+ for (int i = cpList.size() - 1; i >= 0; i--) {
+ X509Certificate cert = (X509Certificate) cpList.get(i);
if (debug != null) {
debug.println("RevocationChecker.buildToNewKey()"
- + " index " + i + " checking "
- + cert);
+ + " index " + i + " checking "
+ + cert);
}
checkCRLs(cert, prevKey2, null, signFlag, true,
- stackedCerts, newAnchors);
+ stackedCerts, newAnchors);
signFlag = certCanSignCrl(cert);
prevKey2 = cert.getPublicKey();
}
@@ -1073,8 +1070,10 @@
// If it doesn't check out, try to find a different key.
// And if we can't find a key, then return false.
PublicKey newKey = cpbr.getPublicKey();
+ X509Certificate newCert = cpList.isEmpty() ?
+ null : (X509Certificate) cpList.get(0);
try {
- checkCRLs(currCert, newKey, (X509Certificate) cpList.get(0),
+ checkCRLs(currCert, newKey, newCert,
true, false, null, params.trustAnchors());
// If that passed, the cert is OK!
return;
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java b/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java
index 9b21a99..7ff8d6c 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java
@@ -35,8 +35,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.Set;
@@ -47,8 +45,7 @@
import sun.security.util.Debug;
/**
- * This class is able to build certification paths in either the forward
- * or reverse directions.
+ * This class builds certification paths in the forward direction.
*
* <p> If successful, it returns a certification path which has successfully
* satisfied all the constraints and requirements specified in the
@@ -102,10 +99,8 @@
/**
* Attempts to build a certification path using the Sun build
* algorithm from a trusted anchor(s) to a target subject, which must both
- * be specified in the input parameter set. By default, this method will
- * attempt to build in the forward direction. In order to build in the
- * reverse direction, the caller needs to pass in an instance of
- * SunCertPathBuilderParameters with the buildForward flag set to false.
+ * be specified in the input parameter set. This method will
+ * attempt to build in the forward direction: from the target to the CA.
*
* <p>The certification path that is constructed is validated
* according to the PKIX specification.
@@ -162,11 +157,7 @@
policyTreeResult = null;
LinkedList<X509Certificate> certPathList = new LinkedList<>();
try {
- if (buildParams.buildForward()) {
- buildForward(adjList, certPathList, searchAllCertStores);
- } else {
- buildReverse(adjList, certPathList);
- }
+ buildForward(adjList, certPathList, searchAllCertStores);
} catch (GeneralSecurityException | IOException e) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception in "
@@ -210,82 +201,6 @@
}
/*
- * Private build reverse method.
- */
- private void buildReverse(List<List<Vertex>> adjacencyList,
- LinkedList<X509Certificate> certPathList)
- throws GeneralSecurityException, IOException
- {
- if (debug != null) {
- debug.println("SunCertPathBuilder.buildReverse()...");
- debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
- + buildParams.initialPolicies());
- }
-
- ReverseState currentState = new ReverseState();
- /* Initialize adjacency list */
- adjacencyList.clear();
- adjacencyList.add(new LinkedList<Vertex>());
-
- /*
- * Perform a search using each trust anchor, until a valid
- * path is found
- */
- Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
- while (iter.hasNext()) {
- TrustAnchor anchor = iter.next();
-
- /* check if anchor satisfies target constraints */
- if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
- this.trustAnchor = anchor;
- this.pathCompleted = true;
- this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
- break;
- }
-
- // skip anchor if it contains a DSA key with no DSA params
- X509Certificate trustedCert = anchor.getTrustedCert();
- PublicKey pubKey = trustedCert != null ? trustedCert.getPublicKey()
- : anchor.getCAPublicKey();
-
- if (PKIX.isDSAPublicKeyWithoutParams(pubKey)) {
- continue;
- }
-
- /* Initialize current state */
- currentState.initState(buildParams);
- currentState.updateState(anchor, buildParams);
-
- currentState.algorithmChecker = new AlgorithmChecker(anchor);
- // Android-removed: Android doesn't use this mechanism for checking untrusted certificates
- // currentState.untrustedChecker = new UntrustedChecker();
- try {
- depthFirstSearchReverse(null, currentState,
- new ReverseBuilder(buildParams),
- adjacencyList, certPathList);
- } catch (GeneralSecurityException | IOException e) {
- // continue on error if more anchors to try
- if (iter.hasNext())
- continue;
- else
- throw e;
- }
-
- // break out of loop if search is successful
- if (pathCompleted) {
- break;
- }
- }
-
- if (debug != null) {
- debug.println("SunCertPathBuilder.buildReverse() returned from "
- + "depthFirstSearchReverse()");
- debug.println("SunCertPathBuilder.buildReverse() "
- + "certPathList.size: " + certPathList.size());
- }
- }
-
- /*
* Private build forward method.
*/
private void buildForward(List<List<Vertex>> adjacencyList,
@@ -634,147 +549,6 @@
}
/*
- * This method performs a depth first search for a certification
- * path while building reverse which meets the requirements set in
- * the parameters object.
- * It uses an adjacency list to store all certificates which were
- * tried (i.e. at one time added to the path - they may not end up in
- * the final path if backtracking occurs). This information can
- * be used later to debug or demo the build.
- *
- * See "Data Structure and Algorithms, by Aho, Hopcroft, and Ullman"
- * for an explanation of the DFS algorithm.
- *
- * @param dN the distinguished name being currently searched for certs
- * @param currentState the current PKIX validation state
- */
- private void depthFirstSearchReverse(X500Principal dN,
- ReverseState currentState,
- ReverseBuilder builder,
- List<List<Vertex>> adjList,
- LinkedList<X509Certificate> cpList)
- throws GeneralSecurityException, IOException
- {
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse(" + dN
- + ", " + currentState.toString() + ")");
-
- /*
- * Find all the certificates issued by dN which
- * satisfy the PKIX certification path constraints.
- */
- Collection<X509Certificate> certs =
- builder.getMatchingCerts(currentState, buildParams.certStores());
- List<Vertex> vertices = addVertices(certs, adjList);
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
- + "certs.size=" + vertices.size());
-
- /*
- * For each cert in the collection, verify anything
- * that hasn't been checked yet (signature, revocation, etc)
- * and check for loops. Call depthFirstSearchReverse()
- * recursively for each good cert.
- */
- for (Vertex vertex : vertices) {
- /**
- * Restore state to currentState each time through the loop.
- * This is important because some of the user-defined
- * checkers modify the state, which MUST be restored if
- * the cert eventually fails to lead to the target and
- * the next matching cert is tried.
- */
- ReverseState nextState = (ReverseState) currentState.clone();
- X509Certificate cert = vertex.getCertificate();
- try {
- builder.verifyCert(cert, nextState, cpList);
- } catch (GeneralSecurityException gse) {
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
- + ": validation failed: " + gse);
- vertex.setThrowable(gse);
- continue;
- }
-
- /*
- * Certificate is good, add it to the path (if it isn't a
- * self-signed cert) and update state
- */
- if (!currentState.isInitial())
- builder.addCertToPath(cert, cpList);
- // save trust anchor
- this.trustAnchor = currentState.trustAnchor;
-
- /*
- * Check if path is completed, return ASAP if so.
- */
- if (builder.isPathCompleted(cert)) {
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
- + ": path completed!");
- pathCompleted = true;
-
- PolicyNodeImpl rootNode = nextState.rootNode;
-
- if (rootNode == null)
- policyTreeResult = null;
- else {
- policyTreeResult = rootNode.copyTree();
- ((PolicyNodeImpl)policyTreeResult).setImmutable();
- }
-
- /*
- * Extract and save the final target public key
- */
- finalPublicKey = cert.getPublicKey();
- if (PKIX.isDSAPublicKeyWithoutParams(finalPublicKey)) {
- finalPublicKey =
- BasicChecker.makeInheritedParamsKey
- (finalPublicKey, currentState.pubKey);
- }
-
- return;
- }
-
- /* Update the PKIX state */
- nextState.updateState(cert);
-
- /*
- * Append an entry for cert in adjacency list and
- * set index for current vertex.
- */
- adjList.add(new LinkedList<Vertex>());
- vertex.setIndex(adjList.size() - 1);
-
- /* recursively search for matching certs at next dN */
- depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
- builder, adjList, cpList);
-
- /*
- * If path has been completed, return ASAP!
- */
- if (pathCompleted) {
- return;
- } else {
- /*
- * If we get here, it means we have searched all possible
- * certs issued by the dN w/o finding any matching certs. This
- * means we have to backtrack to the previous cert in the path
- * and try some other paths.
- */
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
- + ": backtracking");
- if (!currentState.isInitial())
- builder.removeFinalCertFromPath(cpList);
- }
- }
- if (debug != null)
- debug.println("SunCertPathBuilder.depthFirstSearchReverse() all "
- + "certs in this adjacency list checked");
- }
-
- /*
* Adds a collection of matching certificates to the
* adjacency list.
*/
diff --git a/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderParameters.java b/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderParameters.java
deleted file mode 100644
index 186e252..0000000
--- a/ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderParameters.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package sun.security.provider.certpath;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.cert.*;
-import java.util.Set;
-
-/**
- * This class specifies the set of parameters used as input for the Sun
- * certification path build algorithm. It is identical to PKIXBuilderParameters
- * with the addition of a <code>buildForward</code> parameter which allows
- * the caller to specify whether or not the path should be constructed in
- * the forward direction.
- *
- * The default for the <code>buildForward</code> parameter is
- * true, which means that the build algorithm should construct paths
- * from the target subject back to the trusted anchor.
- *
- * @since 1.4
- * @author Sean Mullan
- * @author Yassir Elley
- */
-public class SunCertPathBuilderParameters extends PKIXBuilderParameters {
-
- private boolean buildForward = true;
-
- /**
- * Creates an instance of <code>SunCertPathBuilderParameters</code> with the
- * specified parameter values.
- *
- * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
- * @param targetConstraints a <code>CertSelector</code> specifying the
- * constraints on the target certificate
- * @throws InvalidAlgorithmParameterException if the specified
- * <code>Set</code> is empty <code>(trustAnchors.isEmpty() == true)</code>
- * @throws NullPointerException if the specified <code>Set</code> is
- * <code>null</code>
- * @throws ClassCastException if any of the elements in the <code>Set</code>
- * are not of type <code>java.security.cert.TrustAnchor</code>
- */
- public SunCertPathBuilderParameters(Set<TrustAnchor> trustAnchors,
- CertSelector targetConstraints) throws InvalidAlgorithmParameterException
- {
- super(trustAnchors, targetConstraints);
- setBuildForward(true);
- }
-
- /**
- * Creates an instance of <code>SunCertPathBuilderParameters</code> that
- * uses the specified <code>KeyStore</code> to populate the set
- * of most-trusted CA certificates.
- *
- * @param keystore A keystore from which the set of most-trusted
- * CA certificates will be populated.
- * @param targetConstraints a <code>CertSelector</code> specifying the
- * constraints on the target certificate
- * @throws KeyStoreException if the keystore has not been initialized.
- * @throws InvalidAlgorithmParameterException if the keystore does
- * not contain at least one trusted certificate entry
- * @throws NullPointerException if the keystore is <code>null</code>
- */
- public SunCertPathBuilderParameters(KeyStore keystore,
- CertSelector targetConstraints)
- throws KeyStoreException, InvalidAlgorithmParameterException
- {
- super(keystore, targetConstraints);
- setBuildForward(true);
- }
-
- /**
- * Returns the value of the buildForward flag.
- *
- * @return the value of the buildForward flag
- */
- public boolean getBuildForward() {
- return this.buildForward;
- }
-
- /**
- * Sets the value of the buildForward flag. If true, paths
- * are built from the target subject to the trusted anchor.
- * If false, paths are built from the trusted anchor to the
- * target subject. The default value if not specified is true.
- *
- * @param buildForward the value of the buildForward flag
- */
- public void setBuildForward(boolean buildForward) {
- this.buildForward = buildForward;
- }
-
- /**
- * Returns a formatted string describing the parameters.
- *
- * @return a formatted string describing the parameters.
- */
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("[\n");
- sb.append(super.toString());
- sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n");
- sb.append("]\n");
- return sb.toString();
- }
-}
diff --git a/ojluni/src/main/java/sun/security/util/AbstractAlgorithmConstraints.java b/ojluni/src/main/java/sun/security/util/AbstractAlgorithmConstraints.java
index 1b64d9d..2e851e2 100644
--- a/ojluni/src/main/java/sun/security/util/AbstractAlgorithmConstraints.java
+++ b/ojluni/src/main/java/sun/security/util/AbstractAlgorithmConstraints.java
@@ -46,19 +46,23 @@
// Get algorithm constraints from the specified security property.
static String[] getAlgorithms(String propertyName) {
String property = AccessController.doPrivileged(
- (PrivilegedAction<String>) () -> Security.getProperty(
- propertyName));
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return Security.getProperty(propertyName);
+ }
+ });
+
String[] algorithmsInProperty = null;
if (property != null && !property.isEmpty()) {
// remove double quote marks from beginning/end of the property
- if (property.charAt(0) == '"'
- && property.charAt(property.length() - 1) == '"') {
+ if (property.length() >= 2 && property.charAt(0) == '"' &&
+ property.charAt(property.length() - 1) == '"') {
property = property.substring(1, property.length() - 1);
}
algorithmsInProperty = property.split(",");
- for (int i = 0; i < algorithmsInProperty.length;
- i++) {
+ for (int i = 0; i < algorithmsInProperty.length; i++) {
algorithmsInProperty[i] = algorithmsInProperty[i].trim();
}
}
diff --git a/ojluni/src/main/java/sun/security/util/AnchorCertificates.java b/ojluni/src/main/java/sun/security/util/AnchorCertificates.java
index 6bc0030..8498342 100644
--- a/ojluni/src/main/java/sun/security/util/AnchorCertificates.java
+++ b/ojluni/src/main/java/sun/security/util/AnchorCertificates.java
@@ -56,7 +56,7 @@
try {
cacerts = KeyStore.getInstance("JKS");
try (FileInputStream fis = new FileInputStream(f)) {
- cacerts.load(fis, "changeit".toCharArray());
+ cacerts.load(fis, null);
certs = new HashSet<>();
Enumeration<String> list = cacerts.aliases();
String alias;
diff --git a/ojluni/src/main/java/sun/security/util/DerInputBuffer.java b/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
index b375c60..01f7df5 100644
--- a/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputBuffer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,6 +71,7 @@
return retval;
}
+ // BEGIN Android-added: Added getPos & getSlice, needed for APK parsing
int getPos() {
return pos;
}
@@ -80,6 +81,7 @@
System.arraycopy(buf, startPos, result, 0, size);
return result;
}
+ // END Android-added: Added getPos & getSlice, needed for APK parsing
int peek() throws IOException {
if (pos >= count)
@@ -157,6 +159,11 @@
System.arraycopy(buf, pos, bytes, 0, len);
skip(len);
+ // check to make sure no extra leading 0s for DER
+ if (len >= 2 && (bytes[0] == 0) && (bytes[1] >= 0)) {
+ throw new IOException("Invalid encoding: redundant leading 0s");
+ }
+
if (makePositive) {
return new BigInteger(1, bytes);
} else {
diff --git a/ojluni/src/main/java/sun/security/util/DerInputStream.java b/ojluni/src/main/java/sun/security/util/DerInputStream.java
index dae8afd..b182d4e 100644
--- a/ojluni/src/main/java/sun/security/util/DerInputStream.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -77,7 +77,7 @@
* @param data the buffer from which to create the string (CONSUMED)
*/
public DerInputStream(byte[] data) throws IOException {
- init(data, 0, data.length);
+ init(data, 0, data.length, true);
}
/**
@@ -92,23 +92,48 @@
* starting at "offset"
*/
public DerInputStream(byte[] data, int offset, int len) throws IOException {
- init(data, offset, len);
+ init(data, offset, len, true);
+ }
+
+ /**
+ * Create a DER input stream from part of a data buffer with
+ * additional arg to indicate whether to allow constructed
+ * indefinite-length encoding.
+ * The buffer is not copied, it is shared. Accordingly, the
+ * buffer should be treated as read-only.
+ *
+ * @param data the buffer from which to create the string (CONSUMED)
+ * @param offset the first index of <em>data</em> which will
+ * be read as DER input in the new stream
+ * @param len how long a chunk of the buffer to use,
+ * starting at "offset"
+ * @param allowIndefiniteLength whether to allow constructed
+ * indefinite-length encoding
+ */
+ public DerInputStream(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
+ init(data, offset, len, allowIndefiniteLength);
}
/*
* private helper routine
*/
- private void init(byte[] data, int offset, int len) throws IOException {
+ private void init(byte[] data, int offset, int len,
+ boolean allowIndefiniteLength) throws IOException {
if ((offset+2 > data.length) || (offset+len > data.length)) {
throw new IOException("Encoding bytes too short");
}
// check for indefinite length encoding
if (DerIndefLenConverter.isIndefinite(data[offset+1])) {
- byte[] inData = new byte[len];
- System.arraycopy(data, offset, inData, 0, len);
+ if (!allowIndefiniteLength) {
+ throw new IOException("Indefinite length BER encoding found");
+ } else {
+ byte[] inData = new byte[len];
+ System.arraycopy(data, offset, inData, 0, len);
- DerIndefLenConverter derIn = new DerIndefLenConverter();
- buffer = new DerInputBuffer(derIn.convert(inData));
+ DerIndefLenConverter derIn = new DerIndefLenConverter();
+ buffer = new DerInputBuffer(derIn.convert(inData));
+ }
} else
buffer = new DerInputBuffer(data, offset, len);
buffer.mark(Integer.MAX_VALUE);
@@ -233,12 +258,21 @@
* First byte = number of excess bits in the last octet of the
* representation.
*/
- int validBits = length*8 - buffer.read();
+ int excessBits = buffer.read();
+ if (excessBits < 0) {
+ throw new IOException("Unused bits of bit string invalid");
+ }
+ int validBits = length*8 - excessBits;
+ if (validBits < 0) {
+ throw new IOException("Valid bits of bit string invalid");
+ }
byte[] repn = new byte[length];
- if ((length != 0) && (buffer.read(repn) != length))
- throw new IOException("short read of DER bit string");
+ if ((length != 0) && (buffer.read(repn) != length)) {
+ throw new IOException("Short read of DER bit string");
+ }
+
return new BitArray(validBits, repn);
}
@@ -252,7 +286,7 @@
int length = getLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
return retval;
}
@@ -262,7 +296,7 @@
*/
public void getBytes(byte[] val) throws IOException {
if ((val.length != 0) && (buffer.read(val) != val.length)) {
- throw new IOException("short read of DER octet string");
+ throw new IOException("Short read of DER octet string");
}
}
@@ -384,7 +418,7 @@
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
- int len = getLength((lenByte & 0xff), buffer);
+ int len = getLength(lenByte, buffer);
if (len == -1) {
// indefinite length encoding found
@@ -430,7 +464,7 @@
} while (newstr.available() > 0);
if (newstr.available() != 0)
- throw new IOException("extra data at end of vector");
+ throw new IOException("Extra data at end of vector");
/*
* Now stick them into the array we're returning.
@@ -521,7 +555,7 @@
int length = getLength(buffer);
byte[] retval = new byte[length];
if ((length != 0) && (buffer.read(retval) != length))
- throw new IOException("short read of DER " +
+ throw new IOException("Short read of DER " +
stringName + " string");
return new String(retval, enc);
@@ -582,7 +616,11 @@
*/
static int getLength(int lenByte, InputStream in) throws IOException {
int value, tmp;
+ if (lenByte == -1) {
+ throw new IOException("Short read of DER length");
+ }
+ String mdName = "DerInputStream.getLength(): ";
tmp = lenByte;
if ((tmp & 0x080) == 0x00) { // short form, 1 byte datum
value = tmp;
@@ -596,17 +634,23 @@
if (tmp == 0)
return -1;
if (tmp < 0 || tmp > 4)
- throw new IOException("DerInputStream.getLength(): lengthTag="
- + tmp + ", "
+ throw new IOException(mdName + "lengthTag=" + tmp + ", "
+ ((tmp < 0) ? "incorrect DER encoding." : "too big."));
- for (value = 0; tmp > 0; tmp --) {
+ value = 0x0ff & in.read();
+ tmp--;
+ if (value == 0) {
+ // DER requires length value be encoded in minimum number of bytes
+ throw new IOException(mdName + "Redundant length bytes found");
+ }
+ while (tmp-- > 0) {
value <<= 8;
value += 0x0ff & in.read();
}
if (value < 0) {
- throw new IOException("DerInputStream.getLength(): "
- + "Invalid length bytes");
+ throw new IOException(mdName + "Invalid length bytes");
+ } else if (value <= 127) {
+ throw new IOException(mdName + "Should use short form for length");
}
}
return value;
diff --git a/ojluni/src/main/java/sun/security/util/DerValue.java b/ojluni/src/main/java/sun/security/util/DerValue.java
index 6bca1f7..21116dc 100644
--- a/ojluni/src/main/java/sun/security/util/DerValue.java
+++ b/ojluni/src/main/java/sun/security/util/DerValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -257,7 +257,7 @@
int startPosInInput = in.getPos();
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
DerInputBuffer inbuf = in.dup();
int readLen = inbuf.available();
@@ -375,7 +375,7 @@
tag = (byte)in.read();
byte lenByte = (byte)in.read();
- length = DerInputStream.getLength((lenByte & 0xff), in);
+ length = DerInputStream.getLength(lenByte, in);
if (length == -1) { // indefinite length encoding found
int readLen = in.available();
int offset = 2; // for tag and length bytes
diff --git a/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java b/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
index d8c1462..aecb341 100644
--- a/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
+++ b/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
@@ -56,6 +56,9 @@
public final static String PROPERTY_TLS_DISABLED_ALGS =
"jdk.tls.disabledAlgorithms";
+ // the known security property, jdk.jar.disabledAlgorithms
+ public static final String PROPERTY_JAR_DISABLED_ALGS =
+ "jdk.jar.disabledAlgorithms";
private final String[] disabledAlgorithms;
private final Constraints algorithmConstraints;
@@ -257,14 +260,15 @@
toUpperCase(Locale.ENGLISH));
policy = constraintEntry.substring(space + 1);
} else {
- constraintsMap.computeIfAbsent(
+ constraintsMap.putIfAbsent(
constraintEntry.toUpperCase(Locale.ENGLISH),
- k -> new HashSet<>());
+ new HashSet<>());
continue;
}
// Convert constraint conditions into Constraint classes
- Constraint c, lastConstraint = null;
+ Constraint c = null;
+ Constraint lastConstraint = null;
// Allow only one jdkCA entry per constraint entry
boolean jdkCALimit = false;
@@ -292,11 +296,7 @@
}
c = new jdkCAConstraint(algorithm);
jdkCALimit = true;
- } else {
- throw new IllegalArgumentException("Error in security" +
- " property. Constraint unknown: " + entry);
}
-
// Link multiple conditions for a single constraint
// into a linked list.
if (lastConstraint == null) {
@@ -304,7 +304,9 @@
constraintsMap.putIfAbsent(algorithm,
new HashSet<>());
}
- constraintsMap.get(algorithm).add(c);
+ if (c != null) {
+ constraintsMap.get(algorithm).add(c);
+ }
} else {
lastConstraint.nextConstraint = c;
}
diff --git a/ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java b/ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java
index fa0f530..ed563dc 100644
--- a/ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java
+++ b/ojluni/src/main/java/sun/security/util/SignatureFileVerifier.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,26 +25,49 @@
package sun.security.util;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.CodeSigner;
+import java.security.CryptoPrimitive;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SignatureException;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
-import java.security.*;
-import java.io.*;
-import java.util.*;
-import java.util.jar.*;
-
-import sun.security.pkcs.*;
+import java.util.ArrayList;
import java.util.Base64;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarException;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
import sun.security.jca.Providers;
+import sun.security.pkcs.PKCS7;
+import sun.security.pkcs.SignerInfo;
public class SignatureFileVerifier {
/* Are we debugging ? */
private static final Debug debug = Debug.getInstance("jar");
- /* cache of CodeSigner objects */
+ private static final Set<CryptoPrimitive> DIGEST_PRIMITIVE_SET =
+ Collections.unmodifiableSet(EnumSet.of(CryptoPrimitive.MESSAGE_DIGEST));
+
+ private static final DisabledAlgorithmConstraints JAR_DISABLED_CHECK =
+ new DisabledAlgorithmConstraints(
+ DisabledAlgorithmConstraints.PROPERTY_JAR_DISABLED_ALGS);
+
private ArrayList<CodeSigner[]> signerCache;
private static final String ATTR_DIGEST =
@@ -200,8 +223,15 @@
/** get digest from cache */
- private MessageDigest getDigest(String algorithm)
- {
+ private MessageDigest getDigest(String algorithm) throws SignatureException {
+ // check that algorithm is not restricted
+ if (!JAR_DISABLED_CHECK.permits(DIGEST_PRIMITIVE_SET, algorithm, null)) {
+ SignatureException e =
+ new SignatureException("SignatureFile check failed. " +
+ "Disabled algorithm used: " + algorithm);
+ throw e;
+ }
+
if (createdDigests == null)
createdDigests = new HashMap<String, MessageDigest>();
@@ -321,7 +351,7 @@
private boolean verifyManifestHash(Manifest sf,
ManifestDigester md,
List<Object> manifestDigests)
- throws IOException
+ throws IOException, SignatureException
{
Attributes mattr = sf.getMainAttributes();
boolean manifestSigned = false;
@@ -365,7 +395,7 @@
private boolean verifyManifestMainAttrs(Manifest sf,
ManifestDigester md)
- throws IOException
+ throws IOException, SignatureException
{
Attributes mattr = sf.getMainAttributes();
boolean attrsVerified = true;
@@ -431,14 +461,14 @@
private boolean verifySection(Attributes sfAttr,
String name,
ManifestDigester md)
- throws IOException
+ throws IOException, SignatureException
{
boolean oneDigestVerified = false;
ManifestDigester.Entry mde = md.get(name,block.isOldStyle());
if (mde == null) {
throw new SecurityException(
- "no manifiest section for signature file entry "+name);
+ "no manifest section for signature file entry "+name);
}
if (sfAttr != null) {
diff --git a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
index 58707fb..17ad0e8 100644
--- a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
+++ b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
@@ -122,7 +122,7 @@
return GREGORIAN_INSTANCE;
}
- //Android-changed: remove lazy initialization, use classes instead of class names.
+ // Android-changed: remove lazy initialization, use classes instead of class names.
CalendarSystem cal = calendars.get(calendarName);
if (cal != null) {
diff --git a/ojluni/src/main/native/PlainSocketImpl.c b/ojluni/src/main/native/PlainSocketImpl.c
deleted file mode 100644
index c4b5be7..0000000
--- a/ojluni/src/main/native/PlainSocketImpl.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#if defined(__linux__) && !defined(USE_SELECT)
-#include <sys/poll.h>
-#endif
-#include <netinet/tcp.h> /* Defines TCP_NODELAY, needed for 2.6 */
-#include <netinet/in.h>
-#ifdef __linux__
-#include <netinet/ip.h>
-#endif
-#include <netdb.h>
-#include <stdlib.h>
-
-#ifdef __solaris__
-#include <fcntl.h>
-#endif
-#ifdef __linux__
-#include <unistd.h>
-//#include <sys/sysctl.h>
-#endif
-
-#include "jvm.h"
-#include "jni_util.h"
-#include "net_util.h"
-
-#include "java_net_SocketOptions.h"
-#include "java_net_PlainSocketImpl.h"
-#include "JNIHelp.h"
-
-#define NATIVE_METHOD(className, functionName, signature) \
-{ #functionName, signature, (void*)(className ## _ ## functionName) }
-
-/************************************************************************
- * PlainSocketImpl
- */
-
-static jfieldID IO_fd_fdID;
-
-jfieldID psi_fdID;
-jfieldID psi_addressID;
-jfieldID psi_ipaddressID;
-jfieldID psi_portID;
-jfieldID psi_localportID;
-jfieldID psi_timeoutID;
-jfieldID psi_trafficClassID;
-jfieldID psi_serverSocketID;
-jfieldID psi_fdLockID;
-jfieldID psi_closePendingID;
-
-extern void setDefaultScopeID(JNIEnv *env, struct sockaddr *him);
-
-
-#define SET_NONBLOCKING(fd) { \
- int flags = fcntl(fd, F_GETFL); \
- flags |= O_NONBLOCK; \
- fcntl(fd, F_SETFL, flags); \
-}
-
-#define SET_BLOCKING(fd) { \
- int flags = fcntl(fd, F_GETFL); \
- flags &= ~O_NONBLOCK; \
- fcntl(fd, F_SETFL, flags); \
-}
-
-/*
- * Return the file descriptor given a PlainSocketImpl
- */
-static int getFD(JNIEnv *env, jobject this) {
- jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
- CHECK_NULL_RETURN(fdObj, -1);
- return (*env)->GetIntField(env, fdObj, IO_fd_fdID);
-}
-
-static void PlainSocketImpl_initProto(JNIEnv *env) {
- jclass cls = (*env)->FindClass(env, "java/net/PlainSocketImpl");
- psi_fdID = (*env)->GetFieldID(env, cls , "fd",
- "Ljava/io/FileDescriptor;");
- CHECK_NULL(psi_fdID);
- psi_addressID = (*env)->GetFieldID(env, cls, "address",
- "Ljava/net/InetAddress;");
- CHECK_NULL(psi_addressID);
- psi_portID = (*env)->GetFieldID(env, cls, "port", "I");
- CHECK_NULL(psi_portID);
- psi_localportID = (*env)->GetFieldID(env, cls, "localport", "I");
- CHECK_NULL(psi_localportID);
- psi_timeoutID = (*env)->GetFieldID(env, cls, "timeout", "I");
- CHECK_NULL(psi_timeoutID);
- psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
- CHECK_NULL(psi_trafficClassID);
- psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
- "Ljava/net/ServerSocket;");
- CHECK_NULL(psi_serverSocketID);
- psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
- "Ljava/lang/Object;");
- CHECK_NULL(psi_fdLockID);
- psi_closePendingID = (*env)->GetFieldID(env, cls, "closePending", "Z");
- CHECK_NULL(psi_closePendingID);
- IO_fd_fdID = NET_GetFileDescriptorID(env);
- CHECK_NULL(IO_fd_fdID);
-}
-
-/* a global reference to the java.net.SocketException class. In
- * socketCreate, we ensure that this is initialized. This is to
- * prevent the problem where socketCreate runs out of file
- * descriptors, and is then unable to load the exception class.
- */
-static jclass socketExceptionCls;
-
-/*
- * Class: java_net_PlainSocketImpl
- * Method: socketSetOption0
- * Signature: (IZLjava/lang/Object;)V
- */
-JNIEXPORT void JNICALL
-PlainSocketImpl_socketSetOption0(JNIEnv *env, jobject this,
- jint cmd, jboolean on,
- jobject value) {
- int fd;
- int level, optname, optlen;
- union {
- int i;
- struct linger ling;
- } optval;
-
- /*
- * Check that socket hasn't been closed
- */
- fd = getFD(env, this);
- if (fd < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Socket closed");
- return;
- }
-
- /*
- * SO_TIMEOUT is a NOOP on Solaris/Linux
- */
- if (cmd == java_net_SocketOptions_SO_TIMEOUT) {
- return;
- }
-
- /*
- * Map the Java level socket option to the platform specific
- * level and option name.
- */
- if (NET_MapSocketOption(cmd, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
- return;
- }
-
- switch (cmd) {
- case java_net_SocketOptions_SO_SNDBUF :
- case java_net_SocketOptions_SO_RCVBUF :
- case java_net_SocketOptions_SO_LINGER :
- case java_net_SocketOptions_IP_TOS :
- {
- jclass cls;
- jfieldID fid;
-
- cls = (*env)->FindClass(env, "java/lang/Integer");
- CHECK_NULL(cls);
- fid = (*env)->GetFieldID(env, cls, "value", "I");
- CHECK_NULL(fid);
-
- if (cmd == java_net_SocketOptions_SO_LINGER) {
- if (on) {
- optval.ling.l_onoff = 1;
- optval.ling.l_linger = (*env)->GetIntField(env, value, fid);
- } else {
- optval.ling.l_onoff = 0;
- optval.ling.l_linger = 0;
- }
- optlen = sizeof(optval.ling);
- } else {
- optval.i = (*env)->GetIntField(env, value, fid);
- optlen = sizeof(optval.i);
- }
-
- break;
- }
-
- /* Boolean -> int */
- default :
- optval.i = (on ? 1 : 0);
- optlen = sizeof(optval.i);
-
- }
-
- if (NET_SetSockOpt(fd, level, optname, (const void *)&optval, optlen) < 0) {
-#ifdef __solaris__
- if (errno == EINVAL) {
- // On Solaris setsockopt will set errno to EINVAL if the socket
- // is closed. The default error message is then confusing
- char fullMsg[128];
- jio_snprintf(fullMsg, sizeof(fullMsg), "Invalid option or socket reset by remote peer");
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg);
- return;
- }
-#endif /* __solaris__ */
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Error setting socket option");
- }
-}
-
-/*
- * Class: java_net_PlainSocketImpl
- * Method: socketGetOption
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL
-PlainSocketImpl_socketGetOption(JNIEnv *env, jobject this,
- jint cmd, jobject iaContainerObj) {
-
- int fd;
- int level, optname, optlen;
- union {
- int i;
- struct linger ling;
- } optval;
-
- /*
- * Check that socket hasn't been closed
- */
- fd = getFD(env, this);
- if (fd < 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
- "Socket closed");
- return -1;
- }
-
- /*
- * SO_BINDADDR isn't a socket option
- */
- if (cmd == java_net_SocketOptions_SO_BINDADDR) {
- SOCKADDR him;
- socklen_t len = 0;
- int port;
- jobject iaObj;
- jclass iaCntrClass;
- jfieldID iaFieldID;
-
- len = SOCKADDR_LEN;
-
- if (getsockname(fd, (struct sockaddr *)&him, &len) < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Error getting socket name");
- return -1;
- }
- iaObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
- CHECK_NULL_RETURN(iaObj, -1);
-
- iaCntrClass = (*env)->GetObjectClass(env, iaContainerObj);
- iaFieldID = (*env)->GetFieldID(env, iaCntrClass, "addr", "Ljava/net/InetAddress;");
- CHECK_NULL_RETURN(iaFieldID, -1);
- (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
- return 0; /* notice change from before */
- }
-
- /*
- * Map the Java level socket option to the platform specific
- * level and option name.
- */
- if (NET_MapSocketOption(cmd, &level, &optname)) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Invalid option");
- return -1;
- }
-
- /*
- * Args are int except for SO_LINGER
- */
- if (cmd == java_net_SocketOptions_SO_LINGER) {
- optlen = sizeof(optval.ling);
- } else {
- optlen = sizeof(optval.i);
- }
-
- if (NET_GetSockOpt(fd, level, optname, (void *)&optval, &optlen) < 0) {
- NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
- "Error getting socket option");
- return -1;
- }
-
- switch (cmd) {
- case java_net_SocketOptions_SO_LINGER:
- return (optval.ling.l_onoff ? optval.ling.l_linger: -1);
-
- case java_net_SocketOptions_SO_SNDBUF:
- case java_net_SocketOptions_SO_RCVBUF:
- case java_net_SocketOptions_IP_TOS:
- return optval.i;
-
- default :
- return (optval.i == 0) ? -1 : 1;
- }
-}
-
-
-static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(PlainSocketImpl, socketGetOption, "(ILjava/lang/Object;)I"),
- NATIVE_METHOD(PlainSocketImpl, socketSetOption0, "(IZLjava/lang/Object;)V"),
-};
-
-void register_java_net_PlainSocketImpl(JNIEnv* env) {
- jniRegisterNativeMethods(env, "java/net/PlainSocketImpl", gMethods, NELEM(gMethods));
- PlainSocketImpl_initProto(env);
-}
diff --git a/ojluni/src/main/native/Register.cpp b/ojluni/src/main/native/Register.cpp
index 40c034c..588eedb 100644
--- a/ojluni/src/main/native/Register.cpp
+++ b/ojluni/src/main/native/Register.cpp
@@ -56,7 +56,6 @@
extern void register_java_net_Inet6Address(JNIEnv*);
extern void register_java_net_InetAddress(JNIEnv*);
extern void register_java_net_PlainDatagramSocketImpl(JNIEnv*);
-extern void register_java_net_PlainSocketImpl(JNIEnv*);
extern void register_java_net_SocketInputStream(JNIEnv*);
extern void register_java_net_SocketOutputStream(JNIEnv*);
extern void register_java_nio_Bits(JNIEnv* env);
@@ -125,7 +124,6 @@
register_java_net_InetAddress(env);
register_java_net_Inet4Address(env);
register_java_net_Inet6Address(env);
- register_java_net_PlainSocketImpl(env);
register_java_net_SocketInputStream(env);
register_java_net_SocketOutputStream(env);
register_java_nio_Bits(env);
diff --git a/ojluni/src/main/native/System.c b/ojluni/src/main/native/System.c
index e75e01c..22c4d52 100644
--- a/ojluni/src/main/native/System.c
+++ b/ojluni/src/main/native/System.c
@@ -244,10 +244,6 @@
}
WITH_PLATFORM_STRING(env, javaMessage, message) {
- if (message == NULL) {
- // Since this function is used for last-gasp debugging output, be noisy on failure.
- return;
- }
LOG_PRI(priority, "System", "%s", message);
} END_PLATFORM_STRING(env, message);
diff --git a/ojluni/src/main/native/java_net_SocketOptions.h b/ojluni/src/main/native/java_net_SocketOptions.h
deleted file mode 100644
index e428bb5..0000000
--- a/ojluni/src/main/native/java_net_SocketOptions.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This file was generated from java/net/SocketOptions.java and is licensed
- * under the same terms. The copyright and license information for
- * java/net/SocketOptions.java follows.
- *
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class java_net_SocketOptions */
-
-#ifndef _Included_java_net_SocketOptions
-#define _Included_java_net_SocketOptions
-#ifdef __cplusplus
-extern "C" {
-#endif
-#undef java_net_SocketOptions_TCP_NODELAY
-#define java_net_SocketOptions_TCP_NODELAY 1L
-#undef java_net_SocketOptions_SO_BINDADDR
-#define java_net_SocketOptions_SO_BINDADDR 15L
-#undef java_net_SocketOptions_SO_REUSEADDR
-#define java_net_SocketOptions_SO_REUSEADDR 4L
-#undef java_net_SocketOptions_SO_BROADCAST
-#define java_net_SocketOptions_SO_BROADCAST 32L
-#undef java_net_SocketOptions_IP_MULTICAST_IF
-#define java_net_SocketOptions_IP_MULTICAST_IF 16L
-#undef java_net_SocketOptions_IP_MULTICAST_IF2
-#define java_net_SocketOptions_IP_MULTICAST_IF2 31L
-#undef java_net_SocketOptions_IP_MULTICAST_LOOP
-#define java_net_SocketOptions_IP_MULTICAST_LOOP 18L
-#undef java_net_SocketOptions_IP_TOS
-#define java_net_SocketOptions_IP_TOS 3L
-#undef java_net_SocketOptions_SO_LINGER
-#define java_net_SocketOptions_SO_LINGER 128L
-#undef java_net_SocketOptions_SO_TIMEOUT
-#define java_net_SocketOptions_SO_TIMEOUT 4102L
-#undef java_net_SocketOptions_SO_SNDBUF
-#define java_net_SocketOptions_SO_SNDBUF 4097L
-#undef java_net_SocketOptions_SO_RCVBUF
-#define java_net_SocketOptions_SO_RCVBUF 4098L
-#undef java_net_SocketOptions_SO_KEEPALIVE
-#define java_net_SocketOptions_SO_KEEPALIVE 8L
-#undef java_net_SocketOptions_SO_OOBINLINE
-#define java_net_SocketOptions_SO_OOBINLINE 4099L
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/ojluni/src/main/native/net_util.h b/ojluni/src/main/native/net_util.h
index 839e947..afd94ed 100644
--- a/ojluni/src/main/native/net_util.h
+++ b/ojluni/src/main/native/net_util.h
@@ -78,6 +78,8 @@
extern jclass ia4_class;
extern jmethodID ia4_ctrID;
+/* Android-removed: NetworkInterface moved away fro JNI */
+#if 0
/* NetworkInterface fields */
extern jclass ni_class;
extern jfieldID ni_nameID;
@@ -85,13 +87,17 @@
extern jfieldID ni_addrsID;
extern jfieldID ni_descID;
extern jmethodID ni_ctrID;
+#endif
+/* Android-removed: PlainSocketImpl moved away fro JNI */
+#if 0
/* PlainSocketImpl fields */
extern jfieldID psi_timeoutID;
extern jfieldID psi_fdID;
extern jfieldID psi_addressID;
extern jfieldID psi_portID;
extern jfieldID psi_localportID;
+#endif
/* Android-removed: DatagramSocket moved away from JNI */
#if 0
@@ -138,8 +144,11 @@
void initLocalAddrTable ();
void parseExclusiveBindProperty(JNIEnv *env);
+// Android-removed: unused
+#if 0
void
NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
+#endif
JNIEXPORT jint JNICALL
NET_GetPortFromSockaddr(struct sockaddr *him);
@@ -156,8 +165,11 @@
int
NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
+// Android-removed: unused
+#if 0
int
NET_IsZeroAddr(jbyte* caddr);
+#endif
/* Socket operations
*
@@ -174,11 +186,14 @@
JNIEXPORT int JNICALL
NET_Bind(int fd, struct sockaddr *him, int len);
+// Android-removed: unused
+#if 0
JNIEXPORT int JNICALL
NET_MapSocketOption(jint cmd, int *level, int *optname);
JNIEXPORT int JNICALL
NET_MapSocketOptionV6(jint cmd, int *level, int *optname);
+#endif
int getScopeID (struct sockaddr *);
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
index 49c9779..d15e29d 100644
--- a/ojluni/src/main/native/net_util_md.c
+++ b/ojluni/src/main/native/net_util_md.c
@@ -64,7 +64,11 @@
#include "jvm.h"
#include "net_util.h"
+// Android-removed: unused
+#if 0
#include "java_net_SocketOptions.h"
+#endif
+
/* needed from libsocket on Solaris 8 */
@@ -83,6 +87,8 @@
#define UDP_EXCLBIND 0x0101
#endif
+// Android-removed: unused
+#if 0
void setDefaultScopeID(JNIEnv *env, struct sockaddr *him)
{
#ifdef MACOSX
@@ -124,6 +130,7 @@
ni_defaultIndexID);
return defaultIndex;
}
+#endif
#ifdef __solaris__
static int init_tcp_max_buf, init_udp_max_buf;
@@ -817,6 +824,8 @@
return 0;
}
+// Android-removed: unused
+#if 0
void
NET_SetTrafficClass(struct sockaddr *him, int trafficClass) {
#ifdef AF_INET6
@@ -826,6 +835,7 @@
}
#endif /* AF_INET6 */
}
+#endif
JNIEXPORT jint JNICALL
NET_GetPortFromSockaddr(struct sockaddr *him) {
@@ -876,6 +886,8 @@
return (jboolean)(getaddrinfo_ptr != NULL);
}
+// Android-removed: unused
+#if 0
int NET_IsZeroAddr(jbyte* caddr) {
int i;
for (i = 0; i < 16; i++) {
@@ -885,7 +897,10 @@
}
return 1;
}
+#endif
+// Android-removed: unused
+#if 0
/*
* Map the Java level socket option to the platform specific
* level and option name.
@@ -952,6 +967,7 @@
/* not found */
return -1;
}
+#endif
/*
* Wrapper for getsockopt system routine - does any necessary
@@ -1321,6 +1337,8 @@
return rv;
}
+// Android-removed: unused
+#if 0
/**
* Wrapper for select/poll with timeout on a single file descriptor.
*
@@ -1399,6 +1417,7 @@
return timeout;
}
+#endif
#if 0
// Stripped out unused code.
diff --git a/ojluni/src/main/native/net_util_md.h b/ojluni/src/main/native/net_util_md.h
index 46fa8dd..5c6dd42 100644
--- a/ojluni/src/main/native/net_util_md.h
+++ b/ojluni/src/main/native/net_util_md.h
@@ -112,7 +112,10 @@
#define NET_WAIT_WRITE 0x02
#define NET_WAIT_CONNECT 0x04
+// Android-removed: unused
+#if 0
extern jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
+#endif
/************************************************************************
* Macros and constants
@@ -149,10 +152,13 @@
/************************************************************************
* Utilities
*/
+// Android-removed: unused
+#if 0
#ifdef __linux__
extern int kernelIsV22();
extern int kernelIsV24();
#endif
+#endif
void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name,
const char *defaultDetail);
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 3d37d00..d60bc09 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -50,7 +50,6 @@
Inet6Address.c \
Inet4Address.c \
linux_close.cpp \
- PlainSocketImpl.c \
ServerSocketChannelImpl.c \
SocketInputStream.c \
SocketOutputStream.c \
diff --git a/ojluni/src/test/java/security/cert/PKIXCertPathValidatorValidity.java b/ojluni/src/test/java/security/cert/PKIXCertPathValidatorValidity.java
new file mode 100644
index 0000000..fd68b44
--- /dev/null
+++ b/ojluni/src/test/java/security/cert/PKIXCertPathValidatorValidity.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * @test
+ * @bug 8021804
+ * @summary CertPath should validate even if the validity period of the
+ * root cert does not include the validity period of a subordinate
+ * cert.
+ */
+// Android-changed: Adapted from
+// jdk/test/sun/security/provider/certpath/PKIXCertPathValidator/Validity.java
+// Android-changed: Added package & Test import
+package test.java.security.cert;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+// Android-changed: s/Validity/PKIXCertPathValidatorValidity
+public class PKIXCertPathValidatorValidity {
+
+ /*
+ * Subject: OU=TestOrg, CN=TestCA
+ * Issuer: OU=TestOrg, CN=TestCA
+ * Validity
+ * Not Before: Feb 26 21:33:55 2014 GMT
+ Not After : Feb 26 21:33:55 2024 GMT
+ * Version 1
+ */
+ static String CACertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBvTCCASYCCQCQRiTo4lBCFjANBgkqhkiG9w0BAQUFADAjMRAwDgYDVQQLDAdU\n" +
+ "ZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwHhcNMTQwMjI2MjEzMzU1WhcNMjQwMjI2\n" +
+ "MjEzMzU1WjAjMRAwDgYDVQQLDAdUZXN0T3JnMQ8wDQYDVQQDDAZUZXN0Q0EwgZ8w\n" +
+ "DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOtKS4ZrsM3ansd61ZxitcrN0w184I+A\n" +
+ "z0kyrSP1eMtlam+cC2U91NpTz11FYV4XUfBhqqxaXW043AWTUer8pS90Pt4sCrUX\n" +
+ "COx1+QA1M3ZhbZ4sTM7XQ90JbGaBJ/sEza9mlQP7hQ2yQO/hATKbP6J5qvgG2sT2\n" +
+ "S2WYjEgwNwmFAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAQ/CXEpnx2WY4LJtv4jwE\n" +
+ "4jIVirur3pdzV5oBhPyqqHMsyhQBkukCfX7uD7L5wN1+xuM81DfANpIxlnUfybp5\n" +
+ "CpjcmktLpmyK4kJ6XnSd2blbLOIpsr9x6FqxPxpVDlyw/ySHYrIG/GZdsLHgmzGn\n" +
+ "B06jeYzH8OLf879VxAxSsPc=\n" +
+ "-----END CERTIFICATE-----";
+
+ /*
+ * Subject: OU=TestOrg, CN=TestEE0
+ * Issuer: OU=TestOrg, CN=TestCA
+ * Validity
+ * Not Before: Feb 26 22:55:12 2014 GMT
+ * Not After : Feb 25 22:55:12 2025 GMT
+ * Version 1
+ */
+ static String EECertStr =
+ "-----BEGIN CERTIFICATE-----\n" +
+ "MIIBtjCCAR8CAQQwDQYJKoZIhvcNAQEFBQAwIzEQMA4GA1UECwwHVGVzdE9yZzEP\n" +
+ "MA0GA1UEAwwGVGVzdENBMB4XDTE0MDIyNjIyNTUxMloXDTI1MDIyNTIyNTUxMlow\n" +
+ "JDEQMA4GA1UECwwHVGVzdE9yZzEQMA4GA1UEAwwHVGVzdEVFMDCBnzANBgkqhkiG\n" +
+ "9w0BAQEFAAOBjQAwgYkCgYEAt8xz9W3ruCTHjSOtTX6cxsUZ0nRP6EavEfzgcOYh\n" +
+ "CXGA0gr+viSHq3c2vQBxiRny2hm5rLcqpPo+2OxZtw/ajxfyrV6d/r8YyQLBvyl3\n" +
+ "xdCZdOkG1DCM1oFAQDaSRt9wN5Zm5kyg7uMig5Y4L45fP9Yee4x6Xyh36qYbsR89\n" +
+ "rFMCAwEAATANBgkqhkiG9w0BAQUFAAOBgQDZrPqSo08va1m9TOWOztTuWilGdjK/\n" +
+ "2Ed2WXg8utIpy6uAV+NaOYtHQ7ULQBVRNmwg9nKghbVbh+E/xpoihjl1x7OXass4\n" +
+ "TbwXA5GKFIFpNtDvATQ/QQZoCuCzw1FW/mH0Q7UEQ/9/iJdDad6ebkapeMwtj/8B\n" +
+ "s2IZV7s85CEOXw==\n" +
+ "-----END CERTIFICATE-----";
+
+ // Android-changed: Removed args & added @Test
+ @Test
+ public static void main() throws Exception {
+
+ String[] certStrs = {EECertStr};
+ String[] trustedCertStrs = {CACertStr};
+ runTest(certStrs, trustedCertStrs);
+
+ System.out.println("Test passed.");
+ }
+
+ private static void runTest(String[] certStrs,
+ String[] trustedCertStrs)
+ throws Exception {
+
+ CertificateFactory cf = CertificateFactory.getInstance("X509");
+
+ // Generate the CertPath from the certs named in certStrs
+ ArrayList<X509Certificate> certs = new ArrayList<>();
+ for (String certStr : certStrs) {
+ certs.add(generateCert(certStr, cf));
+ }
+ CertPath cp = cf.generateCertPath(certs);
+
+ // Generate the set of Trust Anchors from the certs named in
+ // trustedCertStrs
+ Set<TrustAnchor> trustAnchors = new HashSet<>();
+ for (String trustedCertStr : trustedCertStrs) {
+ TrustAnchor ta = new TrustAnchor(generateCert(trustedCertStr, cf),
+ null);
+ trustAnchors.add(ta);
+ }
+ PKIXParameters params = new PKIXParameters(trustAnchors);
+ params.setDate(new Date(114, 3, 1)); // 2014-03-01
+ params.setRevocationEnabled(false);
+
+ // Attempt to validate the CertPath. If no exception thrown, successful.
+ CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ cpv.validate(cp, params);
+ System.out.println("CertPath validation successful.");
+ }
+
+ private static X509Certificate generateCert(String certStr,
+ CertificateFactory cf)
+ throws Exception {
+ ByteArrayInputStream stream
+ = new ByteArrayInputStream(certStr.getBytes());
+ return (X509Certificate) cf.generateCertificate(stream);
+
+ }
+}
diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/DoubleStreamTestDataProvider.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/DoubleStreamTestDataProvider.java
index 700d9c9..614cafa 100644
--- a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/DoubleStreamTestDataProvider.java
+++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/DoubleStreamTestDataProvider.java
@@ -35,7 +35,8 @@
private static final double[] to1 = new double[1];
private static final double[] to10 = new double[10];
private static final double[] to100 = new double[100];
- private static final double[] to1000 = new double[1000];
+ // Android-changed: remove 0..1000 test data from data providers.
+ // private static final double[] to1000 = new double[1000];
private static final double[] reversed = new double[100];
private static final double[] ones = new double[100];
private static final double[] twice = new double[200];
@@ -45,7 +46,9 @@
private static final Object[][] spliteratorTestData;
static {
- double[][] arrays = {to0, to1, to10, to100, to1000};
+ // Android-changed: remove 0..1000 test data from data providers.
+ // double[][] arrays = {to0, to1, to10, to100, to1000};
+ double[][] arrays = {to0, to1, to10, to100};
for (double[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
@@ -70,7 +73,8 @@
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
- {"0..1000", to1000},
+ // Android-changed: remove 0..1000 test data from data providers.
+ // {"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/IntStreamTestDataProvider.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/IntStreamTestDataProvider.java
index 972cf31..f80ba4a 100644
--- a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/IntStreamTestDataProvider.java
+++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/IntStreamTestDataProvider.java
@@ -35,7 +35,8 @@
private static final int[] to1 = new int[1];
private static final int[] to10 = new int[10];
private static final int[] to100 = new int[100];
- private static final int[] to1000 = new int[1000];
+ // Android-changed: remove 0..1000 test data from data providers.
+ // private static final int[] to1000 = new int[1000];
private static final int[] reversed = new int[100];
private static final int[] ones = new int[100];
private static final int[] twice = new int[200];
@@ -45,7 +46,8 @@
private static final Object[][] spliteratorTestData;
static {
- int[][] arrays = {to0, to1, to10, to100, to1000};
+ // Android-changed: remove 0..1000 test data from data providers.
+ int[][] arrays = {to0, to1, to10, to100};
for (int[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
@@ -70,7 +72,8 @@
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
- {"0..1000", to1000},
+ // Android-changed: remove 0..1000 test data from data providers.
+ // {"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/LongStreamTestDataProvider.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/LongStreamTestDataProvider.java
index 63a39e6..abee8fd 100644
--- a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/LongStreamTestDataProvider.java
+++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/LongStreamTestDataProvider.java
@@ -35,7 +35,8 @@
private static final long[] to1 = new long[1];
private static final long[] to10 = new long[10];
private static final long[] to100 = new long[100];
- private static final long[] to1000 = new long[1000];
+ // Android-changed: remove 0..1000 test data from data providers.
+ // private static final long[] to1000 = new long[1000];
private static final long[] reversed = new long[100];
private static final long[] ones = new long[100];
private static final long[] twice = new long[200];
@@ -45,7 +46,8 @@
private static final Object[][] spliteratorTestData;
static {
- long[][] arrays = {to0, to1, to10, to100, to1000};
+ // Android-changed: remove 0..1000 test data from data providers.
+ long[][] arrays = {to0, to1, to10, to100};
for (long[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
@@ -70,7 +72,8 @@
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
- {"0..1000", to1000},
+ // Android-changed: remove 0..1000 test data from data providers.
+ // {"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
diff --git a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/StreamTestDataProvider.java b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/StreamTestDataProvider.java
index f933d4c..0c741bf 100644
--- a/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/StreamTestDataProvider.java
+++ b/ojluni/src/test/java/util/stream/testlib/org/openjdk/testlib/java/util/stream/StreamTestDataProvider.java
@@ -42,7 +42,8 @@
private static final Integer[] to1 = new Integer[1];
private static final Integer[] to10 = new Integer[10];
private static final Integer[] to100 = new Integer[100];
- private static final Integer[] to1000 = new Integer[1000];
+ // Android-changed: remove 0..1000 test data from data providers.
+ // private static final Integer[] to1000 = new Integer[1000];
private static final Integer[] reversed = new Integer[100];
private static final Integer[] ones = new Integer[100];
private static final Integer[] twice = new Integer[200];
@@ -53,7 +54,8 @@
private static final Object[][] spliteratorTestData;
static {
- Integer[][] arrays = {to0, to1, to10, to100, to1000};
+ // Android-changed: remove 0..1000 test data from data providers.
+ Integer[][] arrays = {to0, to1, to10, to100};
for (Integer[] arr : arrays) {
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
@@ -78,7 +80,8 @@
{"0..1", to1},
{"0..10", to10},
{"0..100", to100},
- {"0..1000", to1000},
+ // Android-changed: remove 0..1000 test data from data providers.
+ // {"0..1000", to1000},
{"100x[1]", ones},
{"2x[0..100]", twice},
{"reverse 0..100", reversed},
diff --git a/openjdk_java_files.mk b/openjdk_java_files.mk
index 3b38617..7c13ca6 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -1342,6 +1342,26 @@
ojluni/src/main/java/javax/sql/StatementEventListener.java \
ojluni/src/main/java/sun/reflect/CallerSensitive.java \
+# Stubs needed to satisfy javac's dependencies when compiling lambda code. These are
+# not used on Android devices or required by the Jack compiler.
+#
+# On aosp/master:
+# openjdk_lambda_stub_files : These are included in core-oj as stubs
+# openjdk_lambda_duplicate_stub_files : These contain complete implementations in core-oj.
+#
+# On older platforms : Both sets of stub files are used and core-oj does not contain
+# any of these classes.
+openjdk_lambda_stub_files := \
+ ojluni/src/lambda/java/java/lang/invoke/LambdaMetafactory.java \
+ ojluni/src/lambda/java/java/lang/invoke/SerializedLambda.java
+openjdk_lambda_duplicate_stub_files := \
+ ojluni/src/lambda/java/java/lang/invoke/CallSite.java \
+ ojluni/src/lambda/java/java/lang/invoke/MethodHandles.java \
+ ojluni/src/lambda/java/java/lang/invoke/LambdaConversionException.java \
+ ojluni/src/lambda/java/java/lang/invoke/MethodHandle.java \
+ ojluni/src/lambda/java/java/lang/invoke/MethodType.java \
+
+
# NOTE: Files in java/lang/invoke are listed here because they're not being made public
# until the entire package is available for use.
openjdk_java_files := \
@@ -1596,13 +1616,10 @@
ojluni/src/main/java/sun/security/provider/certpath/PKIXMasterCertPathValidator.java \
ojluni/src/main/java/sun/security/provider/certpath/PolicyChecker.java \
ojluni/src/main/java/sun/security/provider/certpath/PolicyNodeImpl.java \
- ojluni/src/main/java/sun/security/provider/certpath/ReverseBuilder.java \
- ojluni/src/main/java/sun/security/provider/certpath/ReverseState.java \
ojluni/src/main/java/sun/security/provider/certpath/RevocationChecker.java \
ojluni/src/main/java/sun/security/provider/certpath/State.java \
ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilder.java \
ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderException.java \
- ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderParameters.java \
ojluni/src/main/java/sun/security/provider/certpath/SunCertPathBuilderResult.java \
ojluni/src/main/java/sun/security/provider/certpath/URICertStore.java \
ojluni/src/main/java/sun/security/provider/certpath/Vertex.java \
@@ -1741,21 +1758,3 @@
$(openjdk_javadoc_files) \
$(openjdk_lambda_stub_files)
-# Stubs needed to satisfy javac's dependencies when compiling lambda code. These are
-# not used on Android devices or required by the Jack compiler.
-#
-# On aosp/master:
-# openjdk_lambda_stub_files : These are included in core-oj as stubs
-# openjdk_lambda_duplicate_stub_files : These contain complete implementations in core-oj.
-#
-# On older platforms : Both sets of stub files are used and core-oj does not contain
-# any of these classes.
-openjdk_lambda_stub_files := \
- ojluni/src/lambda/java/java/lang/invoke/LambdaMetafactory.java \
- ojluni/src/lambda/java/java/lang/invoke/SerializedLambda.java
-openjdk_lambda_duplicate_stub_files := \
- ojluni/src/lambda/java/java/lang/invoke/CallSite.java \
- ojluni/src/lambda/java/java/lang/invoke/MethodHandles.java \
- ojluni/src/lambda/java/java/lang/invoke/LambdaConversionException.java \
- ojluni/src/lambda/java/java/lang/invoke/MethodHandle.java \
- ojluni/src/lambda/java/java/lang/invoke/MethodType.java \
diff --git a/tools/upstream/oj_upstream_comparison.py b/tools/upstream/oj_upstream_comparison.py
index deab5fb..76d63aa 100755
--- a/tools/upstream/oj_upstream_comparison.py
+++ b/tools/upstream/oj_upstream_comparison.py
@@ -85,43 +85,34 @@
return result
return None
-
-# For files with N and M lines, respectively, this runs in time
-# O(N+M) if the files are identical or O(N*M) if not. This could
-# be improved to O(D*(N+M)) for files with at most D lines
-# difference by only considering array elements within D cells
-# from the diagonal.
-def edit_distance_lines(file_a, file_b):
+# For lists of length N and M, respectively, this runs in time O(N*M).
+# This could be improved to O(D*(N+M)) for lists with distance <= D by
+# only considering array elements within D cells of the diagonal.
+def edit_distance(a, b):
"""
- Computes the line-based edit distance between two text files, i.e.
- the smallest number of line deletions, additions or replacements
- that would transform the content of one file into that of the other.
+ Computes the line-based edit distance between two lists, i.e.
+ the smallest number of list items to delete, insert or replace
+ that would transform the content of one list into the other.
"""
- if filecmp.cmp(file_a, file_b, shallow=False):
- return 0 # files identical
- with open(file_a) as f:
- lines_a = f.readlines()
- with open(file_b) as f:
- lines_b = f.readlines()
- prev_cost = range(0, len(lines_b) + 1)
- for end_a in range(1, len(lines_a) + 1):
+ prev_cost = range(0, len(b) + 1)
+ for end_a in range(1, len(a) + 1):
# For each valid index i, prev_cost[i] is the edit distance between
- # lines_a[:end_a-1] and lines_b[:i].
+ # a[:end_a-1] and b[:i].
# We now calculate cur_cost[end_b] as the edit distance between
- # line_a[:end_a] and lines_b[:end_b]
+ # a[:end_a] and b[:end_b]
cur_cost = [end_a]
- for end_b in range(1, len(lines_b) + 1):
+ for end_b in range(1, len(b) + 1):
c = min(
- cur_cost[-1] + 1, # append line from b
- prev_cost[end_b] + 1, # append line from a
- # match or replace line
- prev_cost[end_b - 1] + (0 if lines_a[end_a - 1] == lines_b[end_b - 1] else 1)
+ cur_cost[-1] + 1, # append item from b
+ prev_cost[end_b] + 1, # append item from a
+ # match or replace item
+ prev_cost[end_b - 1] + (0 if a[end_a - 1] == b[end_b - 1] else 1)
)
cur_cost.append(c)
prev_cost = cur_cost
return prev_cost[-1]
-def compare_to_upstreams_and_save(out_file, build_top, upstream_root, upstreams, rel_paths, best_only=False):
+def compare_to_upstreams_and_save(out_file, build_top, upstream_root, upstreams, rel_paths):
"""
Prints tab-separated values comparing ojluni files vs. each
upstream, for each of the rel_paths, suitable for human
@@ -144,13 +135,21 @@
if upstream_file is None:
upstream_comparison = "missing"
else:
- edit_distance = edit_distance_lines(upstream_file, ojluni_file)
- if edit_distance == 0:
+ if filecmp.cmp(upstream_file, ojluni_file, shallow=False):
+ distance = 0
upstream_comparison = "identical"
else:
- upstream_comparison = "different (%d lines)" % (edit_distance)
- if edit_distance < best_distance:
- best_distance = edit_distance
+ with open(upstream_file) as f:
+ lines_a = f.readlines()
+ with open(ojluni_file) as f:
+ lines_b = f.readlines()
+ distance = edit_distance(lines_a, lines_b)
+ # 0% for identical files
+ # 100% for totally different files or where one file is empty
+ percent_different = 100.0 * distance / max(len(lines_a), len(lines_b))
+ upstream_comparison = "%.1f%% different (%d lines)" % (percent_different, distance)
+ if distance < best_distance:
+ best_distance = distance
guessed_upstream = upstream
upstream_comparisons.append(upstream_comparison)
writer.writerow([rel_path, guessed_upstream ] + upstream_comparisons)