Merge changes from topic "am-eb46eb48-7a23-41b3-8b69-98a255b23038" into oc-dev
am: db52df1433
Change-Id: If0c7001adcd8ecb3993e51ababc203ae0a6cdfcb
diff --git a/AndroidTest.xml b/AndroidTest.xml
new file mode 100644
index 0000000..78ed943
--- /dev/null
+++ b/AndroidTest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Config for libjavacore-benchmarks">
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="libjavacore-benchmarks->/data/benchmarktest/libjavacore-benchmarks" />
+ </target_preparer>
+ <option name="test-suite-tag" value="apct" />
+ <test class="com.android.tradefed.testtype.GoogleBenchmarkTest" >
+ <option name="native-benchmark-device-path" value="/data/benchmarktest" />
+ <option name="benchmark-module-name" value="libjavacore-benchmarks" />
+ </test>
+</configuration>
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 5a763da..3466db5 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/NativeCode.mk b/NativeCode.mk
index d8e9d64..9bfb88d 100644
--- a/NativeCode.mk
+++ b/NativeCode.mk
@@ -204,6 +204,7 @@
LOCAL_C_INCLUDES += libcore/include
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := libjavacore-benchmarks
+LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/NativeCode.mk
LOCAL_SHARED_LIBRARIES := libnativehelper
LOCAL_CXX_STL := libc++
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/dalvik/src/main/java/dalvik/system/DexClassLoader.java b/dalvik/src/main/java/dalvik/system/DexClassLoader.java
index 00252a1..db6fb1e 100644
--- a/dalvik/src/main/java/dalvik/system/DexClassLoader.java
+++ b/dalvik/src/main/java/dalvik/system/DexClassLoader.java
@@ -16,8 +16,6 @@
package dalvik.system;
-import java.io.File;
-
/**
* A class loader that loads classes from {@code .jar} and {@code .apk} files
* containing a {@code classes.dex} entry. This can be used to execute code not
@@ -45,8 +43,7 @@
* @param dexPath the list of jar/apk files containing classes and
* resources, delimited by {@code File.pathSeparator}, which
* defaults to {@code ":"} on Android
- * @param optimizedDirectory directory where optimized dex files
- * should be written; must not be {@code null}
+ * @param optimizedDirectory this parameter is deprecated and has no effect
* @param librarySearchPath the list of directories containing native
* libraries, delimited by {@code File.pathSeparator}; may be
* {@code null}
@@ -54,6 +51,6 @@
*/
public DexClassLoader(String dexPath, String optimizedDirectory,
String librarySearchPath, ClassLoader parent) {
- super(dexPath, new File(optimizedDirectory), librarySearchPath, parent);
+ super(dexPath, null, librarySearchPath, parent);
}
}
diff --git a/expectations/brokentests.txt b/expectations/brokentests.txt
deleted file mode 100644
index cd24094..0000000
--- a/expectations/brokentests.txt
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * This file contains expectations for tests that we'd like to eventually fix, but aren't urgent.
- */
-[
-{
- description: "libcore.java.io.OldFileTest#test_deleteOnExit fails on IRM05 mysid-user",
- name: "libcore.java.io.OldFileTest#test_deleteOnExit",
- bug: 5834665
-},
-{
- description: "We're retiring the security manager. Unfortunately, tests all over the place
- need to check that they're secure, so they all fail when we refuse to install
- a security manager. This suppresses all of these failures.",
- result: EXEC_FAILED,
- failure: "disable securityManager",
- pattern: ".*java.lang.SecurityException\\s+at java.lang.System.setSecurityManager.*",
- bug: 2585285
-},
-{
- description: "ignore compilation errors due to different available APIs",
- result: COMPILE_FAILED,
- failure: "ignore compilation errors",
- pattern: ".*\\.java:\\d+: cannot find symbol.*"
-},
-{
- description: "the average length of possible UTF-8 sequences is 2 bytes.",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.java.nio.charset.UTFCharsetEncoderTest#testSpecificDefaultValue",
- substring: "junit.framework.AssertionFailedError: expected:<1.1> but was:<2.0>"
-},
-{
- description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
- result: EXEC_FAILED,
- failure: "connect to the Internet",
- pattern: ".*java.net.UnknownHostException:.*jcltest.apache.org.*"
-},
-{
- description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
- result: EXEC_FAILED,
- names: [
- "com.android.org.apache.harmony.luni.tests.java.net.ExcludedProxyTest"
- ]
-},
-{
- description: "Some tests depend on ICU data, which has changed. Others make assumptions about floating point rounding",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_DateTimeConversion",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_GeneralConversionOther",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_LineSeparator",
- "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_Percent"
- ]
-},
-{
- description: "(Needs investigation) Some tests make assertions that don't make sense, others use broken port allocation logic.",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.net.InetAddressTest#test_isReachableLjava_net_NetworkInterfaceII_loopbackInterface"
- ]
-},
-{
- description: "Potentially flakey because they rely on a specific local TCP port being free.",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.nio.channels.ServerSocketChannelTest#test_bind_explicitPort"
- ]
-},
-{
- description: "The ResourceBundle code under test is probably not used much on Android and needs a lot of attention.",
- modes: [device],
- bug: 13747957,
- names: [
- "org.apache.harmony.tests.java.util.ControlTest#test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ"
- ]
-},
-{
- description: "Fails in CTS, passes in CoreTestRunner.",
- result: EXEC_FAILED,
- modes: [device],
- names: [
- "org.apache.harmony.tests.java.net.URLConnection#test_getContentEncoding",
- "libcore.java.text.OldNumberFormatTest#test_parseLjava_lang_String",
- "libcore.java.nio.channels.OldSocketChannelTest#test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData",
- "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
- "libcore.java.security.cert.OldPKIXParametersTest#testPKIXParametersKeyStore04"
- ]
-},
-{
- description: "Suffers from DH slowness, disabling for now.",
- result: EXEC_FAILED,
- names: [
- "libcore.java.security.OldDHTest#testDHGen",
- "libcore.java.security.OldKeyPairGeneratorTestDH#testKeyPairGenerator",
- "libcore.javax.crypto.spec.KeyPairGeneratorTestDH#testKeyPairGenerator",
- "libcore.javax.crypto.spec.AlgorithmParametersTestDH#testAlgorithmParameters",
- "libcore.javax.crypto.spec.AlgorithmParameterGeneratorTestDH#testAlgorithmParameterGenerator"
- ]
-},
-{
- description: "Destroys MD5 provider, hurts succeeding tests",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKey",
- "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKeyString"
- ]
-},
-{
- description: "Support_TestWebServer requires isolation.",
- result: EXEC_FAILED,
- names: [
- "libcore.java.net.OldURLClassLoaderTest#test_findResourceLjava_lang_String"
- ]
-},
-{
- description: "Causes OutOfMemoryError to test finalization",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.java.lang.ref.SoftReferenceTest#test_get_SoftReference",
- "org.apache.harmony.crypto.tests.javax.crypto#ExemptionMechanismTest#test_finalize"
- ]
-},
-{
- description: "Causes open dex file error",
- modes: [device],
- names: [
- "org.apache.harmony.tests.java.lang.reflect.GenericSignatureFormatErrorTest#test_signatureFormatError"
- ]
-},
-{
- description: "Requires functional Support_Jetty",
- bug: 28535961,
- result: EXEC_FAILED,
- names: [
- "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderTest"
- ]
-},
-{
- description: "Unable to execute Support_AvailTest",
- result: EXEC_FAILED,
- bug: 28535603,
- names: [
- "com.android.org.apache.harmony.luni.tests.internal.process.SystemProcessTest#test_interrupt"
- ]
-}
-]
diff --git a/expectations/icebox.txt b/expectations/icebox.txt
deleted file mode 100644
index db9e3ad..0000000
--- a/expectations/icebox.txt
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * This file contains expectations for tests that we'd like to eventually fix, but aren't urgent.
- */
-[
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testEntityDeclarations",
- substring: "This implementation does not parse entity declarations"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testGetWholeTextWithEntityReference",
- substring: "This implementation doesn't resolve entity references in getWholeText"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- name: "libcore.xml.DomTest#testExpandingEntityReferencesOff",
- bug: 3268630,
- substring: "This implementation doesn't include children in entity references"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- name: "libcore.xml.DomTest#testExpandingEntityReferencesOn",
- bug: 3268630,
- substring: "This implementation doesn't expand entity references"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testIsElementContentWhitespaceWithDeclaration",
- substring: "This implementation does not recognize element content whitespace"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DomTest#testNotations",
- substring: "This implementation does not parse notations"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- names: [
- "tests.org.w3c.dom.HCNotationsRemoveNamedItemNS#testRemoveNamedItemNS",
- "tests.org.w3c.dom.HCNotationsSetNamedItemNS#testNotationsSetNamedItemNS"
- ]
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlEncoding",
- substring: "This implementation doesn't parse the encoding from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlStandalone",
- substring: "This implementation doesn't parse standalone from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.DeclarationTest#testGetXmlVersion",
- substring: "This implementation doesn't parse the version from the XML declaration"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "libcore.xml.NormalizeTest#testSchemaTypeDtd",
- substring: "This implementation's setParameter() supports an unexpected value: schema-type=http://www.w3.org/TR/REC-xml"
-},
-{
- description: "Dalvik doesn't support XML Schemas, DTDs or validation",
- bug: 3268630,
- name: "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testSetEntityResolver",
- substring: "java.lang.ClassCastException: org.apache.harmony.xml.dom.EntityReferenceImpl"
-},
-{
- description: "many tests attempt to fork a Java executable, but fork the wrong one",
- result: "EXEC_FAILED",
- failure: "should fork a dalvikvm, not a JVM",
- substring: "/system/bin.*IOException"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testAttributeNamedIdIsNotAnIdByDefault",
- substring: "This implementation incorrectly interprets the \"id\" attribute as an identifier by default"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testDocumentAddChild",
- substring: "Document nodes shouldn't accept child nodes"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testElementTraversalFeature",
- substring: "This implementation is expected to support ElementTraversal v. 1.0 but does not."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.DomTest#testLoadSaveFeature",
- substring: "This implementation is expected to support LS v. 3.0 but does not."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "libcore.xml.SaxTest#testYesPrefixesYesNamespaces",
- substring: "The 'namespace-prefix' feature is not supported while the 'namespaces' feature is enabled."
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_newInstance",
- substring: "Expected FactoryConfigurationError was not thrown"
-},
-{
- description: "low-impact XML bugs:",
- result: EXEC_FAILED,
- names: [
- "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderFactoryTest#test_isSetXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testIsXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_setIsXIncludeAware",
- "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#testIsXIncludeAware"
- ],
- substring: "java.lang.UnsupportedOperationException: This parser does not support specification \"Unknown\" version \"0.0\""
-},
-{
- description: "a low-impact bug, also present in Crockford's implementation of org.json",
- result: EXEC_FAILED,
- name: "org.json.ParsingTest#test64BitHexValues",
- substring: "Large hex longs shouldn't be yield ints or strings expected:<-1> but was:<0xFFFFFFFFFFFFFFFF>"
-},
-{
- description: "this test needs to be fixed. We supply optional qnames, but this test doesn't expect them",
- result: EXEC_FAILED,
- name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String"
-},
-{
- description: "BouncyCastle allows unrecognized algorithms, but RI does not, not clear if this is a bug",
- result: EXEC_FAILED,
- name: "org.apache.harmony.crypto.tests.javax.crypto.KeyAgreementTest#test_generateSecretLjava_lang_String",
- substring: "junit.framework.AssertionFailedError: NoSuchAlgorithmException expected"
-}
-]
diff --git a/expectations/knownfailures.txt b/expectations/knownfailures.txt
index 1c0acf4..2d60453 100644
--- a/expectations/knownfailures.txt
+++ b/expectations/knownfailures.txt
@@ -1,8 +1,49 @@
/*
- * This file contains expectations for tests that were annotated with @KnownFailure at the time
+ * This file contains test expectations for libcore.
+ * TODO: Rename this file to account for the fact that it has both tags and known failures
*/
[
{
+ description: "large tests",
+ result: SUCCESS,
+ names: [
+ /* libcore tests that take over 15 minutes on device because of DHParametersHelper.generateSafePrimes */
+ "org.apache.harmony.crypto.tests.javax.crypto.func.KeyAgreementFunctionalTest",
+ "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPrivateKeyTest",
+ "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPublicKeyTest",
+ /* non-AOSP tests http://b/8027066 */
+ "java.util.EnumSet.EnumSetBash",
+ "java.io.PipedInputStream.CloseAndAvailableRC",
+ "java.io.PrintStream.OversynchronizedTest",
+ "java.io.PrintWriter.OversynchronizedTest",
+ "java.lang.String.Split",
+ "java.lang.ref.SoftReference.Pin",
+ "java.math.BigInteger.BigIntegerTest",
+ "java.net.MulticastSocket.Test",
+ "java.net.Socket.InheritTimeout",
+ "java.net.Socket.reset.Test",
+ "java.net.URLConnection.TimeoutTest",
+ "java.nio.channels.DatagramChannel.ConnectedSend",
+ "java.nio.channels.FileChannel.ExpandingMap",
+ "java.nio.channels.FileChannel.Transfers",
+ "java.nio.channels.SocketChannel.Open",
+ "java.text.Bidi.Bug6665028",
+ "java.util.Collections.FindSubList",
+ "java.util.Locale.Bug4518797",
+ "java.util.ResourceBundle.Control.StressTest",
+ "java.util.WeakHashMap.GCDuringIteration",
+ "java.util.concurrent.FutureTask.Throw",
+ "java.util.concurrent.locks.ReentrantReadWriteLock.MapLoops",
+ "java.util.zip.LargeZip",
+ "java.util.zip.ZipFile.LargeZipFile",
+ "java.util.zip.ZipFile.ManyEntries",
+ "libcore.java.lang.SystemTest_testArrayCopyConcurrentModification",
+ "sun.nio.cs.FindOneCharEncoderBugs",
+ "sun.nio.cs.SurrogateGB18030Test"
+ ],
+ "tags": [ "large" ]
+},
+{
description: "can't compile a pattern with negative look-behind and quantifiers with upper bounds",
result: EXEC_FAILED,
name: "org.apache.harmony.regex.tests.java.util.regex.PatternTest#test_bug_40103",
@@ -1505,11 +1546,321 @@
]
},
{
+ description: "Bouncy Castle doesn't prevent reusing initialization vectors",
+ bug: 31801320,
+ result: EXEC_FAILED,
+ names: [
+ "com.google.security.wycheproof.AesGcmTest#testIvReuse"
+ ]
+},
+{
+ description: "Conscrypt produces different exceptions under different circumstances",
+ bug: 36772622,
+ result: EXEC_FAILED,
+ names: [
+ "com.google.security.wycheproof.RsaEncryptionTest#testExceptionsPKCS1",
+ "com.google.security.wycheproof.RsaEncryptionTest#testGetExceptionsOAEP"
+ ]
+},
+{
+ description: "Conscrypt fails these tests in 32-bit mode",
+ bug: 36636626,
+ result: EXEC_FAILED,
+ names: [
+ "com.google.security.wycheproof.EcdhTest#testModifiedPublic",
+ "com.google.security.wycheproof.EcdhTest#testModifiedPublicSpec"
+ ]
+},
+{
description: "Bullhead kernel does not block send when buffer is supposed to have saturated",
bug: 36691333,
result: EXEC_FAILED,
names: [
"libcore.java.net.SocketTimeoutTest#testSocketWriteNeverTimeouts"
]
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testEntityDeclarations",
+ substring: "This implementation does not parse entity declarations"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testGetWholeTextWithEntityReference",
+ substring: "This implementation doesn't resolve entity references in getWholeText"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ name: "libcore.xml.DomTest#testExpandingEntityReferencesOff",
+ bug: 3268630,
+ substring: "This implementation doesn't include children in entity references"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ name: "libcore.xml.DomTest#testExpandingEntityReferencesOn",
+ bug: 3268630,
+ substring: "This implementation doesn't expand entity references"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testIsElementContentWhitespaceWithDeclaration",
+ substring: "This implementation does not recognize element content whitespace"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DomTest#testNotations",
+ substring: "This implementation does not parse notations"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ names: [
+ "tests.org.w3c.dom.HCNotationsRemoveNamedItemNS#testRemoveNamedItemNS",
+ "tests.org.w3c.dom.HCNotationsSetNamedItemNS#testNotationsSetNamedItemNS"
+ ]
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlEncoding",
+ substring: "This implementation doesn't parse the encoding from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlStandalone",
+ substring: "This implementation doesn't parse standalone from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.DeclarationTest#testGetXmlVersion",
+ substring: "This implementation doesn't parse the version from the XML declaration"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "libcore.xml.NormalizeTest#testSchemaTypeDtd",
+ substring: "This implementation's setParameter() supports an unexpected value: schema-type=http://www.w3.org/TR/REC-xml"
+},
+{
+ description: "Dalvik doesn't support XML Schemas, DTDs or validation",
+ bug: 3268630,
+ name: "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testSetEntityResolver",
+ substring: "java.lang.ClassCastException: org.apache.harmony.xml.dom.EntityReferenceImpl"
+},
+{
+ description: "many tests attempt to fork a Java executable, but fork the wrong one",
+ result: "EXEC_FAILED",
+ failure: "should fork a dalvikvm, not a JVM",
+ substring: "/system/bin.*IOException"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testAttributeNamedIdIsNotAnIdByDefault",
+ substring: "This implementation incorrectly interprets the \"id\" attribute as an identifier by default"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testDocumentAddChild",
+ substring: "Document nodes shouldn't accept child nodes"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testElementTraversalFeature",
+ substring: "This implementation is expected to support ElementTraversal v. 1.0 but does not."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.DomTest#testLoadSaveFeature",
+ substring: "This implementation is expected to support LS v. 3.0 but does not."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "libcore.xml.SaxTest#testYesPrefixesYesNamespaces",
+ substring: "The 'namespace-prefix' feature is not supported while the 'namespaces' feature is enabled."
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_newInstance",
+ substring: "Expected FactoryConfigurationError was not thrown"
+},
+{
+ description: "low-impact XML bugs:",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderFactoryTest#test_isSetXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.DocumentBuilderTest#testIsXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.SAXParserFactoryTest#test_setIsXIncludeAware",
+ "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#testIsXIncludeAware"
+ ],
+ substring: "java.lang.UnsupportedOperationException: This parser does not support specification \"Unknown\" version \"0.0\""
+},
+{
+ description: "a low-impact bug, also present in Crockford's implementation of org.json",
+ result: EXEC_FAILED,
+ name: "org.json.ParsingTest#test64BitHexValues",
+ substring: "Large hex longs shouldn't be yield ints or strings expected:<-1> but was:<0xFFFFFFFFFFFFFFFF>"
+},
+{
+ description: "this test needs to be fixed. We supply optional qnames, but this test doesn't expect them",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.javax.xml.parsers.SAXParserTest#test_parseLjava_io_InputStreamLorg_xml_sax_helpers_DefaultHandlerLjava_lang_String"
+},
+{
+ description: "BouncyCastle allows unrecognized algorithms, but RI does not, not clear if this is a bug",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.crypto.tests.javax.crypto.KeyAgreementTest#test_generateSecretLjava_lang_String",
+ substring: "junit.framework.AssertionFailedError: NoSuchAlgorithmException expected"
+},
+{
+ description: "libcore.java.io.OldFileTest#test_deleteOnExit fails on IRM05 mysid-user",
+ name: "libcore.java.io.OldFileTest#test_deleteOnExit",
+ bug: 5834665
+},
+{
+ description: "We're retiring the security manager. Unfortunately, tests all over the place
+ need to check that they're secure, so they all fail when we refuse to install
+ a security manager. This suppresses all of these failures.",
+ result: EXEC_FAILED,
+ failure: "disable securityManager",
+ pattern: ".*java.lang.SecurityException\\s+at java.lang.System.setSecurityManager.*",
+ bug: 2585285
+},
+{
+ description: "ignore compilation errors due to different available APIs",
+ result: COMPILE_FAILED,
+ failure: "ignore compilation errors",
+ pattern: ".*\\.java:\\d+: cannot find symbol.*"
+},
+{
+ description: "the average length of possible UTF-8 sequences is 2 bytes.",
+ result: EXEC_FAILED,
+ name: "org.apache.harmony.tests.java.nio.charset.UTFCharsetEncoderTest#testSpecificDefaultValue",
+ substring: "junit.framework.AssertionFailedError: expected:<1.1> but was:<2.0>"
+},
+{
+ description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
+ result: EXEC_FAILED,
+ failure: "connect to the Internet",
+ pattern: ".*java.net.UnknownHostException:.*jcltest.apache.org.*"
+},
+{
+ description: "Some tests (ExcludedProxyTest) connect to a public webserver to check that the HTTP client works",
+ result: EXEC_FAILED,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.java.net.ExcludedProxyTest"
+ ]
+},
+{
+ description: "Some tests depend on ICU data, which has changed. Others make assumptions about floating point rounding",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_DateTimeConversion",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_GeneralConversionOther",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_LineSeparator",
+ "org.apache.harmony.tests.java.util.FormatterTest#test_formatLjava_lang_String$Ljava_lang_Object_Percent"
+ ]
+},
+{
+ description: "(Needs investigation) Some tests make assertions that don't make sense, others use broken port allocation logic.",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.net.InetAddressTest#test_isReachableLjava_net_NetworkInterfaceII_loopbackInterface"
+ ]
+},
+{
+ description: "Potentially flakey because they rely on a specific local TCP port being free.",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.nio.channels.ServerSocketChannelTest#test_bind_explicitPort"
+ ]
+},
+{
+ description: "The ResourceBundle code under test is probably not used much on Android and needs a lot of attention.",
+ modes: [device],
+ bug: 13747957,
+ names: [
+ "org.apache.harmony.tests.java.util.ControlTest#test_needsReload_LStringLLocaleLStringLClassLoaderResourceBundleJ"
+ ]
+},
+{
+ description: "Fails in CTS, passes in CoreTestRunner.",
+ result: EXEC_FAILED,
+ modes: [device],
+ names: [
+ "org.apache.harmony.tests.java.net.URLConnection#test_getContentEncoding",
+ "libcore.java.text.OldNumberFormatTest#test_parseLjava_lang_String",
+ "libcore.java.nio.channels.OldSocketChannelTest#test_writeLjava_nio_ByteBuffer_Nonblocking_HugeData",
+ "org.apache.harmony.tests.java.lang.ProcessManagerTest#testSleep",
+ "libcore.java.security.cert.OldPKIXParametersTest#testPKIXParametersKeyStore04"
+ ]
+},
+{
+ description: "Suffers from DH slowness, disabling for now.",
+ result: EXEC_FAILED,
+ names: [
+ "libcore.java.security.OldDHTest#testDHGen",
+ "libcore.java.security.OldKeyPairGeneratorTestDH#testKeyPairGenerator",
+ "libcore.javax.crypto.spec.KeyPairGeneratorTestDH#testKeyPairGenerator",
+ "libcore.javax.crypto.spec.AlgorithmParametersTestDH#testAlgorithmParameters",
+ "libcore.javax.crypto.spec.AlgorithmParameterGeneratorTestDH#testAlgorithmParameterGenerator"
+ ]
+},
+{
+ description: "Destroys MD5 provider, hurts succeeding tests",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKey",
+ "org.apache.harmony.tests.api.javax.security.cert.X509CertificateTest#testVerifyPublicKeyString"
+ ]
+},
+{
+ description: "Support_TestWebServer requires isolation.",
+ result: EXEC_FAILED,
+ names: [
+ "libcore.java.net.OldURLClassLoaderTest#test_findResourceLjava_lang_String"
+ ]
+},
+{
+ description: "Causes OutOfMemoryError to test finalization",
+ result: EXEC_FAILED,
+ names: [
+ "org.apache.harmony.tests.java.lang.ref.SoftReferenceTest#test_get_SoftReference",
+ "org.apache.harmony.crypto.tests.javax.crypto#ExemptionMechanismTest#test_finalize"
+ ]
+},
+{
+ description: "Causes open dex file error",
+ modes: [device],
+ names: [
+ "org.apache.harmony.tests.java.lang.reflect.GenericSignatureFormatErrorTest#test_signatureFormatError"
+ ]
+},
+{
+ description: "Requires functional Support_Jetty",
+ bug: 28535961,
+ result: EXEC_FAILED,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.java.net.URLClassLoaderTest"
+ ]
+},
+{
+ description: "Unable to execute Support_AvailTest",
+ result: EXEC_FAILED,
+ bug: 28535603,
+ names: [
+ "com.android.org.apache.harmony.luni.tests.internal.process.SystemProcessTest#test_interrupt"
+ ]
}
]
diff --git a/expectations/taggedtests.txt b/expectations/taggedtests.txt
deleted file mode 100644
index cc2a4d6..0000000
--- a/expectations/taggedtests.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * This file contains expectations for tests that require support from the test runner to complete
- * successfully.
- */
-[
-{
- description: "large tests",
- result: SUCCESS,
- names: [
- /* libcore tests that take over 15 minutes on device because of DHParametersHelper.generateSafePrimes */
- "org.apache.harmony.crypto.tests.javax.crypto.func.KeyAgreementFunctionalTest",
- "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPrivateKeyTest",
- "org.apache.harmony.crypto.tests.javax.crypto.interfaces.DHPublicKeyTest",
- /* non-AOSP tests http://b/8027066 */
- "java.util.EnumSet.EnumSetBash",
- "java.io.PipedInputStream.CloseAndAvailableRC",
- "java.io.PrintStream.OversynchronizedTest",
- "java.io.PrintWriter.OversynchronizedTest",
- "java.lang.String.Split",
- "java.lang.ref.SoftReference.Pin",
- "java.math.BigInteger.BigIntegerTest",
- "java.net.MulticastSocket.Test",
- "java.net.Socket.InheritTimeout",
- "java.net.Socket.reset.Test",
- "java.net.URLConnection.TimeoutTest",
- "java.nio.channels.DatagramChannel.ConnectedSend",
- "java.nio.channels.FileChannel.ExpandingMap",
- "java.nio.channels.FileChannel.Transfers",
- "java.nio.channels.SocketChannel.Open",
- "java.text.Bidi.Bug6665028",
- "java.util.Collections.FindSubList",
- "java.util.Locale.Bug4518797",
- "java.util.ResourceBundle.Control.StressTest",
- "java.util.WeakHashMap.GCDuringIteration",
- "java.util.concurrent.FutureTask.Throw",
- "java.util.concurrent.locks.ReentrantReadWriteLock.MapLoops",
- "java.util.zip.LargeZip",
- "java.util.zip.ZipFile.LargeZipFile",
- "java.util.zip.ZipFile.ManyEntries",
- "libcore.java.lang.SystemTest_testArrayCopyConcurrentModification",
- "sun.nio.cs.FindOneCharEncoderBugs",
- "sun.nio.cs.SurrogateGB18030Test"
- ],
- "tags": [ "large" ]
-}
-]
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
index 19a63af..601d522 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/io/PrintStreamTest.java
@@ -19,6 +19,7 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.FilterOutputStream;
import java.io.InputStreamReader;
import java.io.DataInputStream;
import java.io.File;
@@ -27,9 +28,16 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Base64;
import java.util.Locale;
+import libcore.io.IoUtils;
public class PrintStreamTest extends junit.framework.TestCase {
+ private static final String UNICODE_STRING =
+ "K\u03B1\u03BB\u03B7\u00B5\u03B5\u00B4\u03C1\u03B1 \u03BA\u03BF\u00B4\u03C3\u00B5\u03B5";
ByteArrayOutputStream bos = new ByteArrayOutputStream();
@@ -70,19 +78,16 @@
* {@link java.io.PrintStream#PrintStream(String)}
*/
public void test_Constructor_Ljava_lang_String() throws IOException {
- MockPrintStream os = new MockPrintStream(testFilePath);
- assertNotNull(os);
+ PrintStream os = new PrintStream(testFilePath);
+ os.print(UNICODE_STRING);
os.close();
+ assertFileContents(UNICODE_STRING.getBytes(Charset.defaultCharset()), testFile);
}
/**
* {@link java.io.PrintStream#PrintStream(String, String)}
*/
public void test_Constructor_Ljava_lang_String_Ljava_lang_String() throws Exception {
- MockPrintStream os = new MockPrintStream(testFilePath, "utf-8");
- assertNotNull(os);
- os.close();
-
// Test that a bogus charset is mentioned in the exception
try {
new PrintStream(testFilePath, "Bogus");
@@ -90,6 +95,20 @@
} catch (UnsupportedEncodingException e) {
assertNotNull(e.getMessage());
}
+
+ {
+ PrintStream os = new PrintStream(testFilePath, "utf-8");
+ os.print(UNICODE_STRING);
+ os.close();
+ assertFileContents(UNICODE_STRING.getBytes(StandardCharsets.UTF_8), testFile);
+ }
+
+ {
+ PrintStream os = new PrintStream(testFilePath, "utf-16");
+ os.print(UNICODE_STRING);
+ os.close();
+ assertFileContents(UNICODE_STRING.getBytes(StandardCharsets.UTF_16), testFile);
+ }
}
/**
@@ -124,7 +143,7 @@
/**
* java.io.PrintStream#PrintStream(java.io.OutputStream, boolean, String)
*/
- public void test_ConstructorLjava_io_OutputStreamZLjava_lang_String() {
+ public void test_ConstructorLjava_io_OutputStreamZLjava_lang_String() throws Exception {
try {
new PrintStream(new ByteArrayOutputStream(), false,
"%Illegal_name!");
@@ -132,6 +151,24 @@
} catch (UnsupportedEncodingException e) {
// expected
}
+
+ {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ PrintStream printStream = new PrintStream(bos, true /* autoFlush */, "utf-8");
+ printStream.print(UNICODE_STRING);
+ printStream.close();
+ assertByteArraysEqual(UNICODE_STRING.getBytes(StandardCharsets.UTF_8),
+ bos.toByteArray());
+ }
+
+ {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ PrintStream printStream = new PrintStream(bos, true /* autoFlush */, "utf-16");
+ printStream.print(UNICODE_STRING);
+ printStream.close();
+ assertByteArraysEqual(UNICODE_STRING.getBytes(StandardCharsets.UTF_16),
+ bos.toByteArray());
+ }
}
/**
@@ -626,6 +663,59 @@
}
/**
+ * Tests that a PrintStream with {@code autoFlush == true} will call
+ * {@link OutputStream#flush()} at least once, after the last byte
+ * was written.
+ */
+ public void test_autoFlush_flushesEverything() {
+ CountFlushOutputStream counter = new CountFlushOutputStream(new ByteArrayOutputStream());
+ PrintStream printStream = new PrintStream(counter, true /* autoFlush */);
+ printStream.print("Hello, world!");
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.print(Math.PI);
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.print("\n");
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.println();
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.println("Lots\nof\nnewlines\n");
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.print("Line 1\nLine 2\n".toCharArray());
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+
+ byte[] bytes = "Line without a newline".getBytes(StandardCharsets.UTF_8);
+ printStream.write(bytes, 0, bytes.length);
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ }
+
+ /**
+ * Tests that a PrintStream with {@code autoFlush == false} will not
+ * call {@link OutputStream#flush()} in regular (non-error) operation.
+ */
+ public void test_noAutoFlush() {
+ CountFlushOutputStream counter = new CountFlushOutputStream(new ByteArrayOutputStream());
+ PrintStream printStream = new PrintStream(counter, false /* autoFlush */);
+ printStream.print("Hello, world!");
+ printStream.print(Math.PI);
+ printStream.print("\n");
+ printStream.println();
+ printStream.println("Lots\nof\nnewlines\n");
+ printStream.print("Line 1\nLine 2\n".toCharArray());
+ byte[] bytes = "Line without a newline".getBytes(StandardCharsets.UTF_8);
+ printStream.write(bytes, 0, bytes.length);
+ assertFalse(counter.hasEverBeenFlushed());
+ assertFalse(counter.hasBeenFlushedSinceLastWrite());
+
+ // checkError() still causes the PrintStream to flush(), even when autoFlush == false.
+ printStream.checkError();
+ assertTrue(counter.hasEverBeenFlushed());
+ assertTrue(counter.hasBeenFlushedSinceLastWrite());
+ printStream.print("This data\nwill not be flushed.");
+ assertTrue(counter.hasEverBeenFlushed());
+ assertFalse(counter.hasBeenFlushedSinceLastWrite());
+ }
+
+ /**
* java.io.PrintStream#printf(java.lang.String, java.lang.Object...)
*/
public void test_printfLjava_lang_String$Ljava_lang_Object() {
@@ -669,5 +759,47 @@
super.tearDown();
}
+ private static void assertByteArraysEqual(byte[] expected, byte[] actual) {
+ String message = "Expected " + Base64.getEncoder().encodeToString(expected) + ", got: "
+ + Base64.getEncoder().encodeToString(actual);
+ assertTrue(message, Arrays.equals(actual, expected));
+ }
+
+ private static void assertFileContents(byte[] expected, File file) throws IOException {
+ byte[] actual = IoUtils.readFileAsByteArray(file.getAbsolutePath());
+ assertByteArraysEqual(expected, actual);
+ }
+
+ static class CountFlushOutputStream extends FilterOutputStream {
+ private boolean hasBeenFlushedSinceLastWrite = false;
+ private boolean hasEverBeenFlushed = false;
+
+ public CountFlushOutputStream(OutputStream delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ super.write(b);
+ hasBeenFlushedSinceLastWrite = false;
+ }
+
+ @Override
+ public void flush() throws IOException {
+ super.flush();
+ hasBeenFlushedSinceLastWrite = true;
+ hasEverBeenFlushed = true;
+ }
+
+ /** Whether {@link #flush()} has been called since the last write. */
+ public boolean hasBeenFlushedSinceLastWrite() {
+ return hasBeenFlushedSinceLastWrite;
+ }
+
+ /** Whether {@link #flush()} has ever been called after this stream was constructed. */
+ public boolean hasEverBeenFlushed() {
+ return hasEverBeenFlushed;
+ }
+ }
}
diff --git a/luni/src/main/java/android/system/OsConstants.java b/luni/src/main/java/android/system/OsConstants.java
index 20a4a47..2e6fc1b 100644
--- a/luni/src/main/java/android/system/OsConstants.java
+++ b/luni/src/main/java/android/system/OsConstants.java
@@ -357,6 +357,7 @@
public static final int MS_ASYNC = placeholder();
public static final int MS_INVALIDATE = placeholder();
public static final int MS_SYNC = placeholder();
+ /** @hide */ public static final int NETLINK_NETFILTER = placeholder();
/** @hide */ public static final int NETLINK_ROUTE = placeholder();
public static final int NI_DGRAM = placeholder();
public static final int NI_NAMEREQD = placeholder();
diff --git a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
index a981c18..3d12664 100644
--- a/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
+++ b/luni/src/main/java/java/nio/charset/CharsetEncoderICU.java
@@ -74,6 +74,7 @@
byte[] replacement = makeReplacement(icuCanonicalName, address);
CharsetEncoderICU result = new CharsetEncoderICU(cs, averageBytesPerChar, maxBytesPerChar, replacement, address);
address = 0; // CharsetEncoderICU has taken ownership; its finalizer will do the free.
+ result.updateCallback();
return result;
} finally {
if (address != 0) {
@@ -97,7 +98,6 @@
// Our native peer needs to know what just happened...
this.converterHandle = address;
NativeConverter.registerConverter(this, converterHandle);
- updateCallback();
}
@Override protected void implReplaceWith(byte[] newReplacement) {
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/java/libcore/util/TimeZoneFinder.java b/luni/src/main/java/libcore/util/TimeZoneFinder.java
index 4e47df4..37e3b4a 100644
--- a/luni/src/main/java/libcore/util/TimeZoneFinder.java
+++ b/luni/src/main/java/libcore/util/TimeZoneFinder.java
@@ -80,6 +80,7 @@
// VisibleForTesting
public static TimeZoneFinder createInstanceWithFallback(String... tzLookupFilePaths) {
+ IOException lastException = null;
for (String tzLookupFilePath : tzLookupFilePaths) {
try {
// We assume that any file in /data was validated before install, and the system
@@ -87,12 +88,18 @@
// validation cost here.
return createInstance(tzLookupFilePath);
} catch (IOException e) {
- System.logE("Unable to process file: " + tzLookupFilePath + " Trying next one.", e);
+ // There's expected to be two files, and it's normal for the first file not to
+ // exist so we don't log, but keep the lastException so we can log it if there
+ // are no valid files available.
+ if (lastException != null) {
+ e.addSuppressed(lastException);
+ }
+ lastException = e;
}
}
System.logE("No valid file found in set: " + Arrays.toString(tzLookupFilePaths)
- + " Falling back to empty map.");
+ + " Printing exceptions and falling back to empty map.", lastException);
return createInstanceForTests("<timezones><countryzones /></timezones>");
}
@@ -124,8 +131,8 @@
}
/**
- * Return a time zone that has / would have had the specified offset and DST value at the
- * specified moment in the specified country.
+ * Returns a frozen ICU time zone that has / would have had the specified offset and DST value
+ * at the specified moment in the specified country.
*
* <p>In order to be considered a configured zone must match the supplied offset information.
*
@@ -186,10 +193,11 @@
}
/**
- * Returns a list of time zones known to be used in the specified country. If the country code
- * is not recognized or there is an error during lookup this can return null. The TimeZones
- * returned will never contain {@link TimeZone#UNKNOWN_ZONE}. This method can return an empty
- * list in a case when the underlying configuration references only unknown zone IDs.
+ * Returns an immutable list of frozen ICU time zones known to be used in the specified country.
+ * If the country code is not recognized or there is an error during lookup this can return
+ * null. The TimeZones returned will never contain {@link TimeZone#UNKNOWN_ZONE}. This method
+ * can return an empty list in a case when the underlying configuration references only unknown
+ * zone IDs.
*/
public List<TimeZone> lookupTimeZonesByCountry(String countryIso) {
synchronized(this) {
diff --git a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
index d30e7a3..c4f25e0 100644
--- a/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
+++ b/luni/src/main/native/libcore_icu_TimeZoneNames.cpp
@@ -46,10 +46,7 @@
}
static bool setStringArrayElement(JNIEnv* env, jobjectArray array, int i, const icu::UnicodeString& s) {
- // Fill in whatever we got. We don't use the display names if they're "GMT[+-]xx:xx"
- // because icu4c doesn't use the up-to-date time zone transition data, so it gets these
- // wrong. TimeZone.getDisplayName creates accurate names on demand.
- // TODO: investigate whether it's worth doing that work once in the Java wrapper instead of on-demand.
+ // Don't use "GMT" string, for backwards compatibility.
static const icu::UnicodeString kGmt("GMT", 3, US_INV);
if (!s.isBogus() && !s.startsWith(kGmt)) {
ScopedLocalRef<jstring> javaString(env, env->NewString(s.getBuffer(), s.length()));
diff --git a/luni/src/test/java/dalvik/system/DexClassLoaderTest.java b/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
index 625cfa9..a99cc23 100644
--- a/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
+++ b/luni/src/test/java/dalvik/system/DexClassLoaderTest.java
@@ -16,8 +16,6 @@
package dalvik.system;
-import java.io.FilenameFilter;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.io.File;
import java.io.FileOutputStream;
@@ -37,7 +35,6 @@
private File dex2;
private File jar1;
private File jar2;
- private File optimizedDir;
protected void setUp() throws Exception {
srcDir = File.createTempFile("src", "");
@@ -53,15 +50,10 @@
copyResource("loading-test2.dex", dex2);
copyResource("loading-test.jar", jar1);
copyResource("loading-test2.jar", jar2);
-
- optimizedDir = File.createTempFile("optimized", "");
- assertTrue(optimizedDir.delete());
- assertTrue(optimizedDir.mkdirs());
}
protected void tearDown() {
cleanUpDir(srcDir);
- cleanUpDir(optimizedDir);
}
private static void cleanUpDir(File dir) {
@@ -99,13 +91,6 @@
}
}
- static final FilenameFilter DEX_FILE_NAME_FILTER = new FilenameFilter() {
- @Override
- public boolean accept(File file, String s) {
- return s.endsWith(".dex");
- }
- };
-
/**
* Helper to construct a DexClassLoader instance to test.
*
@@ -118,7 +103,7 @@
for (int i = 1; i < files.length; i++) {
path += File.pathSeparator + files[i].getAbsolutePath();
}
- return new DexClassLoader(path, optimizedDir.getAbsolutePath(), null,
+ return new DexClassLoader(path, null, null,
ClassLoader.getSystemClassLoader());
}
diff --git a/luni/src/test/java/libcore/java/lang/OldThreadGroupTest.java b/luni/src/test/java/libcore/java/lang/OldThreadGroupTest.java
index 206fdce..35e366e 100644
--- a/luni/src/test/java/libcore/java/lang/OldThreadGroupTest.java
+++ b/luni/src/test/java/libcore/java/lang/OldThreadGroupTest.java
@@ -67,6 +67,8 @@
}
private ThreadGroup initialThreadGroup = null;
+ // A thread that runs in initialThreadGroup throughout each test.
+ private MyThread initialThread;
private List<MyThread> myThreads;
public void test_activeGroupCount() {
@@ -100,27 +102,14 @@
tg.allowThreadSuspension(true));
}
- /*
- * Checks whether the current Thread is in the given list.
- */
- private boolean inListOfThreads(Thread[] threads) {
- for (int i = 0; i < threads.length; i++) {
- if (Thread.currentThread() == threads[i]) {
- return true;
- }
- }
-
- return false;
- }
-
public void test_enumerateLThreadArray() {
int numThreads = initialThreadGroup.activeCount();
Thread[] listOfThreads = new Thread[numThreads];
int countThread = initialThreadGroup.enumerate(listOfThreads);
assertEquals(numThreads, countThread);
- assertTrue("Current thread must be in enumeration of threads",
- inListOfThreads(listOfThreads));
+ assertTrue("Initial thread must be in enumeration of threads",
+ Arrays.asList(listOfThreads).contains(initialThread));
}
public void test_enumerateLThreadArrayLZtest_enumerateLThreadArrayLZ() throws Exception {
@@ -129,14 +118,14 @@
Thread[] initialThreads = new Thread[initialThreadCount];
assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, false));
assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true));
- assertTrue(inListOfThreads(initialThreads));
+ assertTrue(Arrays.asList(initialThreads).contains(initialThread));
// start some the threads and see how the count changes
ThreadGroup group = new ThreadGroup(initialThreadGroup, "enumerateThreadArray");
int groupSize = 3;
List<MyThread> newThreads = populateGroupsWithThreads(group, groupSize);
assertEquals(initialThreadCount, initialThreadGroup.enumerate(initialThreads, true));
- assertTrue(inListOfThreads(initialThreads));
+ assertTrue(Arrays.asList(initialThreads).contains(initialThread));
for(MyThread thread : newThreads) {
thread.start();
}
@@ -148,7 +137,7 @@
Thread[] afterStartThreads = new Thread[afterStartCount];
assertEquals(afterStartCount, initialThreadGroup.enumerate(afterStartThreads, true));
assertEquals(initialPlusNew, new HashSet<Thread>(Arrays.asList(afterStartThreads)));
- assertTrue(inListOfThreads(afterStartThreads));
+ assertTrue(Arrays.asList(afterStartThreads).contains(initialThread));
// kill the threads and count 'em again
for(MyThread thread : newThreads) {
@@ -159,7 +148,7 @@
Thread[] afterDeathThreads = new Thread[afterDeathCount];
assertEquals(afterDeathCount, initialThreadGroup.enumerate(afterDeathThreads, false));
assertEquals(Arrays.asList(initialThreads), Arrays.asList(afterDeathThreads));
- assertTrue(inListOfThreads(afterDeathThreads));
+ assertTrue(Arrays.asList(afterDeathThreads).contains(initialThread));
}
public void test_enumerateLThreadGroupArray() {
@@ -167,7 +156,7 @@
ThreadGroup childGroup = new ThreadGroup(initialThreadGroup, "child group");
int numChildGroupsAfter = initialThreadGroup.activeGroupCount();
- assertTrue(initialThreadGroup.toString(), numChildGroupsAfter == numChildGroupsBefore + 1);
+ assertEquals(initialThreadGroup.toString(), numChildGroupsBefore + 1, numChildGroupsAfter);
ThreadGroup[] listOfGroups = new ThreadGroup[numChildGroupsAfter];
int countGroupThread = initialThreadGroup.enumerate(listOfGroups);
@@ -183,12 +172,12 @@
countGroupThread = initialThreadGroup.enumerate(listOfGroups2);
assertEquals(numChildGroupsAfter - 1, countGroupThread);
- ThreadGroup thrGroup1 = new ThreadGroup("Test Group 1");
+ ThreadGroup thrGroup1 = new ThreadGroup(initialThreadGroup, "Test Group 1");
countGroupThread = thrGroup1.enumerate(listOfGroups);
assertEquals(0, countGroupThread);
childGroup.destroy();
- assertTrue(initialThreadGroup.activeGroupCount() == numChildGroupsBefore + 1);
+ assertEquals(numChildGroupsBefore + 1, initialThreadGroup.activeGroupCount());
}
public void test_enumerateLThreadGroupArrayLZ() {
@@ -240,6 +229,11 @@
assertEquals(1, thrGroup.enumerate(listOfGroups, false));
}
+ public void test_getParent() {
+ assertEquals(Thread.currentThread().getThreadGroup(), new ThreadGroup("test").getParent());
+ assertEquals(initialThreadGroup, new ThreadGroup(initialThreadGroup, "test").getParent());
+ }
+
/**
* java.lang.ThreadGroup#interrupt()
*/
@@ -326,7 +320,11 @@
@Override
protected void setUp() {
myThreads = new ArrayList<>();
- initialThreadGroup = Thread.currentThread().getThreadGroup();
+ initialThreadGroup = new ThreadGroup(Thread.currentThread().getThreadGroup(), "test group");
+ initialThread = new MyThread(initialThreadGroup, "initial thread");
+ myThreads.add(initialThread);
+ initialThread.start();
+
ThreadGroup rootThreadGroup = initialThreadGroup;
while (rootThreadGroup.getParent() != null) {
rootThreadGroup = rootThreadGroup.getParent();
diff --git a/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
index 6d5a6c2..90a40df 100644
--- a/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
+++ b/luni/src/test/java/libcore/java/lang/reflect/parameter/README.txt
@@ -8,7 +8,7 @@
Regenerate the .dex files with:
make smali
-smali libcore/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetdataTestClasses*.smali \
+smali assemble libcore/luni/src/test/java/libcore/java/lang/reflect/parameter/ParameterMetdataTestClasses*.smali \
-o libcore/luni/src/test/resources/libcore/java/lang/reflect/parameter/parameter_metadata_test_classes.dex
For reference, the valid smali code should be (roughly) the equivalent of the
diff --git a/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
index 435dce2..74948f6 100644
--- a/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
+++ b/luni/src/test/java/libcore/java/net/FtpURLConnectionTest.java
@@ -42,16 +42,13 @@
import java.util.Collections;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.Random;
-import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
- import sun.net.ftp.FtpLoginException;
+import sun.net.ftp.FtpLoginException;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -61,10 +58,10 @@
public class FtpURLConnectionTest extends TestCase {
private static final String FILE_PATH = "test/file/for/FtpURLConnectionTest.txt";
- private static final String USER = "user";
- private static final String PASSWORD = "password";
private static final String SERVER_HOSTNAME = "localhost";
- private static final String USER_HOME_DIR = "/home/user";
+ private static final String VALID_USER = "user";
+ private static final String VALID_PASSWORD = "password";
+ private static final String VALID_USER_HOME_DIR = "/home/user";
private FakeFtpServer fakeFtpServer;
private UnixFakeFileSystem fileSystem;
@@ -74,10 +71,11 @@
super.setUp();
fakeFtpServer = new FakeFtpServer();
fakeFtpServer.setServerControlPort(0 /* allocate port number automatically */);
- fakeFtpServer.addUserAccount(new UserAccount(USER, PASSWORD, USER_HOME_DIR));
+ fakeFtpServer.addUserAccount(new UserAccount(VALID_USER, VALID_PASSWORD,
+ VALID_USER_HOME_DIR));
fileSystem = new UnixFakeFileSystem();
fakeFtpServer.setFileSystem(fileSystem);
- fileSystem.add(new DirectoryEntry(USER_HOME_DIR));
+ fileSystem.add(new DirectoryEntry(VALID_USER_HOME_DIR));
fakeFtpServer.start();
}
@@ -89,17 +87,45 @@
public void testInputUrl() throws Exception {
byte[] fileContents = "abcdef 1234567890".getBytes(UTF_8);
- URL fileUrl = addFileEntry(FILE_PATH, fileContents);
+ addFileEntry(FILE_PATH, fileContents);
+ URL fileUrl = getFileUrlWithCredentials(VALID_USER, VALID_PASSWORD, FILE_PATH);
URLConnection connection = fileUrl.openConnection();
assertContents(fileContents, connection.getInputStream());
}
+ public void testInputUrl_invalidUserOrPassword() throws Exception {
+ checkInputUrl_invalidUserOrPassword("wrong_user", VALID_PASSWORD);
+ checkInputUrl_invalidUserOrPassword(VALID_USER, "wrong password");
+ }
+
+ public void testInputUrl_missingPassword() throws Exception {
+ URL noPasswordUrl = getFileUrlWithCredentials(VALID_USER, null, FILE_PATH);
+ URLConnection noPasswordConnection = noPasswordUrl.openConnection();
+ try {
+ noPasswordConnection.getInputStream();
+ fail();
+ } catch (IOException expected) {
+ }
+ }
+
+ private void checkInputUrl_invalidUserOrPassword(String user, String password)
+ throws IOException {
+ URL fileUrl = getFileUrlWithCredentials(user, password, FILE_PATH);
+ URLConnection connection = fileUrl.openConnection();
+ try {
+ connection.getInputStream();
+ fail();
+ } catch (sun.net.ftp.FtpLoginException expected) {
+ assertEquals("Invalid username/password", expected.getMessage());
+ }
+ }
+
public void testOutputUrl() throws Exception {
byte[] fileContents = "abcdef 1234567890".getBytes(UTF_8);
addFileEntry("test/output-url/existing file.txt", fileContents);
byte[] newFileContents = "contents of brand new file".getBytes(UTF_8);
String filePath = "test/output-url/file that is newly created.txt";
- URL fileUrl = new URL(getFileUrlString(filePath));
+ URL fileUrl = getFileUrlWithCredentials(VALID_USER, VALID_PASSWORD, filePath);
URLConnection connection = fileUrl.openConnection();
connection.setDoInput(false);
connection.setDoOutput(true);
@@ -223,8 +249,36 @@
}
}
+ // http://b/35784677
+ public void testCRLFInUserinfo() throws Exception {
+ int serverPort = fakeFtpServer.getServerControlPort();
+ List<String> encodedUserInfos = Arrays.asList(
+ // '\r\n' in the username with password
+ "user%0D%0Acommand:password",
+ // '\r\n' in the password
+ "user:password%0D%0Acommand",
+ // just '\n' in the password
+ "user:password%0Acommand",
+ // just '\n' in the username
+ "user%0Acommand:password"
+ );
+ for (String encodedUserInfo : encodedUserInfos) {
+ String urlString = String.format(Locale.US, "ftp://%s@%s:%s/%s",
+ encodedUserInfo, SERVER_HOSTNAME, serverPort, FILE_PATH);
+ try {
+ new URL(urlString).openConnection().connect();
+ fail("Connection shouldn't have succeeded: " + urlString);
+ } catch (FtpLoginException expected) {
+ // The original message "Illegal carriage return" gets lost
+ // where FtpURLConnection.connect() translates the
+ // original FtpProtocolException into FtpLoginException.
+ assertEquals("Invalid username/password", expected.getMessage());
+ }
+ }
+ }
+
private InputStream openFileSystemContents(String fileName) throws IOException {
- String fullFileName = USER_HOME_DIR + "/" + fileName;
+ String fullFileName = VALID_USER_HOME_DIR + "/" + fileName;
FileEntry entry = (FileEntry) fileSystem.getEntry(fullFileName);
assertNotNull("File must exist with name " + fullFileName, entry);
return entry.createInputStream();
@@ -249,61 +303,13 @@
}
}
- // http://b/35784677
- public void testCRLFInUserinfo() throws Exception {
- List<String> encodedUserInfos = Arrays.asList(
- // '\r\n' in the username with password
- "user%0D%0Acommand:password",
- // '\r\n' in the password
- "user:password%0D%0Acommand",
- // just '\n' in the password
- "user:password%0Acommand",
- // just '\n' in the username
- "user%0Acommand:password"
- );
- for (String encodedUserInfo : encodedUserInfos) {
- ExecutorService executor = Executors.newSingleThreadExecutor();
- ServerSocket mockFtpServerSocket = new ServerSocket(0);
- Future<Void> future = executor.submit(new Callable<Void>() {
- @Override public Void call() throws Exception {
- Socket clientSocket = mockFtpServerSocket.accept();
- clientSocket.getOutputStream().write("220 o/".getBytes());
- clientSocket.close();
- return null;
- }
- });
- executor.shutdown();
-
- String urlString = String.format(Locale.US, "ftp://%s@%s:%s/%s",
- encodedUserInfo, SERVER_HOSTNAME, mockFtpServerSocket.getLocalPort(), FILE_PATH);
- try {
- new URL(urlString).openConnection().connect();
- fail("Connection shouldn't have succeeded: " + urlString);
- } catch (FtpLoginException expected) {
- // The original message "Illegal carriage return" gets lost
- // where FtpURLConnection.connect() translates the
- // original FtpProtocolException into FtpLoginException.
- assertEquals("Invalid username/password", expected.getMessage());
- }
-
- // Cleanup
- future.get();
- mockFtpServerSocket.close();
- }
- }
-
- private String getFileUrlString(String filePath) {
+ private URL getFileUrlWithCredentials(String user, String password, String filePath) {
+ Objects.requireNonNull(user);
+ Objects.requireNonNull(filePath);
int serverPort = fakeFtpServer.getServerControlPort();
- String urlString = String.format(Locale.US, "ftp://%s:%s@%s:%s/%s",
- USER, PASSWORD, SERVER_HOSTNAME, serverPort, filePath);
- return urlString;
- }
-
- private URL addFileEntry(String filePath, byte[] fileContents) {
- FileEntry fileEntry = new FileEntry(USER_HOME_DIR + "/" + filePath);
- fileEntry.setContents(fileContents);
- fileSystem.add(fileEntry);
- String urlString = getFileUrlString(filePath);
+ String credentials = user + (password == null ? "" : (":" + password));
+ String urlString = String.format(Locale.US, "ftp://%s@%s:%s/%s",
+ credentials, SERVER_HOSTNAME, serverPort, filePath);
try {
return new URL(urlString);
} catch (MalformedURLException e) {
@@ -312,6 +318,13 @@
}
}
+ private URL addFileEntry(String filePath, byte[] fileContents) {
+ FileEntry fileEntry = new FileEntry(VALID_USER_HOME_DIR + "/" + filePath);
+ fileEntry.setContents(fileContents);
+ fileSystem.add(fileEntry);
+ return getFileUrlWithCredentials(VALID_USER, VALID_PASSWORD, filePath);
+ }
+
/**
* A {@link ProxySelector} that selects the same (given) Proxy for all URIs.
*/
diff --git a/luni/src/test/java/libcore/java/text/OldBidiTest.java b/luni/src/test/java/libcore/java/text/OldBidiTest.java
index fe8b6cb..08edbcd 100644
--- a/luni/src/test/java/libcore/java/text/OldBidiTest.java
+++ b/luni/src/test/java/libcore/java/text/OldBidiTest.java
@@ -205,4 +205,35 @@
assertFalse("Latin bidi is mixed: " + latin, latin.isMixed());
assertTrue("latin bidi is not left to right: " + latin, latin.isLeftToRight());
}
+
+ // Regression test for http://b/34320622 - when specifying "embeddings" of 0 with RTL characters
+ // and a default of LTR we should not get an exception.
+ public void testEmbeddings() throws Exception {
+ char[] text = new char[2];
+ text[0] = '\u202d'; // LEFT-TO-RIGHT OVERRIDE
+ text[1] = '\u05d0'; // HEBREW LETTER ALEF
+
+ byte[] embeddings = new byte[2];
+ embeddings[0] = 0;
+ embeddings[1] = 0;
+ int flags = Bidi.DIRECTION_DEFAULT_LEFT_TO_RIGHT;
+
+ // This threw an exception on N.
+ Bidi bidi = new Bidi(text, 0, embeddings, 0, 2, flags);
+
+ // Assert properties of the resulting Bidi and embeddings array. The results are somewhat
+ // arbitrary and it's hard to know the user's expectations for the characters chosen, but
+ // a failure will identify unintended behavior changes.
+ assertEquals(text.length, bidi.getLength());
+ assertEquals(1, bidi.getBaseLevel());
+ assertEquals(1, bidi.getRunCount());
+ assertEquals(1, bidi.getLevelAt(0));
+ assertEquals(1, bidi.getLevelAt(1));
+ assertEquals(1, bidi.getRunLevel(0));
+ assertEquals(0, bidi.getRunStart(0));
+ assertEquals(2, bidi.getRunLimit(0));
+
+ assertEquals(0, embeddings[0]);
+ assertEquals(0, embeddings[1]);
+ }
}
diff --git a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
index 20fa986..d1deae1 100644
--- a/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
+++ b/luni/src/test/java/libcore/java/text/SimpleDateFormatTest.java
@@ -583,4 +583,33 @@
assertNull(parsed);
assertEquals("Wrong error index", 5, pos.getErrorIndex());
}
+
+ // http://b/38396219
+ public void testDisplayNamesOnNonGregorianCalendar() {
+ assertEquals("Jan", formatDateNonGregorianCalendar("MMM")); // MONTH
+ assertEquals("Jan", formatDateNonGregorianCalendar("LLL")); // MONTH_STANDALONE
+ assertEquals("Thu", formatDateNonGregorianCalendar("EEE")); // DAY_OF_WEEK
+ assertEquals("Thu", formatDateNonGregorianCalendar("ccc")); // STANDALONE_DAY_OF_WEEK
+ }
+
+ /**
+ * Format a date using a "non-gregorian" calendar. This means that we use a calendar that is not
+ * exactly {@code java.util.GregorianCalendar} as checked by
+ * {@link SimpleDateFormat#isGregorianCalendar()}.
+ */
+ private static String formatDateNonGregorianCalendar(String fmt) {
+ DateFormat dateFormat = new SimpleDateFormat(fmt, Locale.US);
+ NonGregorianCalendar cal = new NonGregorianCalendar();
+ cal.clear();
+ cal.setTimeZone(UTC);
+ dateFormat.setCalendar(cal);
+ return dateFormat.format(new Date(0));
+ }
+
+ /**
+ * Calendar that pretends that it's not a GregorianCalendar, for {@link
+ * #testDisplayNamesOnNonGregorianCalendar()}.
+ */
+ private static class NonGregorianCalendar extends GregorianCalendar {
+ }
}
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/javax/net/ssl/SSLSocketFactoryTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
index 1ddeacb..ebf72f0 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketFactoryTest.java
@@ -20,6 +20,7 @@
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
+import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
@@ -249,4 +250,15 @@
assertNotNull(ssl);
assertTrue(SSLSocket.class.isAssignableFrom(ssl.getClass()));
}
+
+
+ public void test_SSLSocketFactory_createSocket_withConsumedInputStream()
+ throws Exception {
+ try {
+ SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ Socket sslSocket = sf.createSocket(null, (InputStream) null, false);
+ fail();
+ } catch (UnsupportedOperationException expected) {
+ }
+ }
}
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/luni/src/test/java/libcore/sun/net/util/IPAddressUtilTest.java b/luni/src/test/java/libcore/sun/net/util/IPAddressUtilTest.java
new file mode 100644
index 0000000..9294309
--- /dev/null
+++ b/luni/src/test/java/libcore/sun/net/util/IPAddressUtilTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.sun.net.util;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+import static sun.net.util.IPAddressUtil.textToNumericFormatV4;
+
+public class IPAddressUtilTest extends TestCase {
+
+ public void test_textToNumericFormatV4_valid() {
+ assertBytesEquals(0, 0, 0, 0, textToNumericFormatV4("0.0.0.0"));
+ assertBytesEquals(1, 2, 3, 4, textToNumericFormatV4("1.2.3.4"));
+ assertBytesEquals(255, 255, 255, 255, textToNumericFormatV4("255.255.255.255"));
+ assertBytesEquals(123, 23, 255, 37, textToNumericFormatV4("123.23.255.37"));
+ assertBytesEquals(192, 168, 0, 42, textToNumericFormatV4("192.168.0.42"));
+ }
+
+ public void test_textToNumericFormatV4_invalid() {
+ // Wrong number of components
+ assertNull(textToNumericFormatV4("1"));
+ assertNull(textToNumericFormatV4("1.2"));
+ assertNull(textToNumericFormatV4("1.2.3"));
+ assertNull(textToNumericFormatV4("1.2.3.4.5"));
+
+ // Extra dots in various places
+ assertNull(textToNumericFormatV4("1..3.4"));
+ assertNull(textToNumericFormatV4("1..2.3.4"));
+ assertNull(textToNumericFormatV4(".1.2.3"));
+ assertNull(textToNumericFormatV4(".1.2.3.4"));
+ assertNull(textToNumericFormatV4("1.2.3.4."));
+
+ // Out of bounds values
+ assertNull(textToNumericFormatV4("256.2.3.4"));
+ assertNull(textToNumericFormatV4("1.256.3.4"));
+ assertNull(textToNumericFormatV4("1.2.256.4"));
+ assertNull(textToNumericFormatV4("1.2.3.256"));
+ assertNull(textToNumericFormatV4("1.-2.3.4"));
+ }
+
+ private static void assertBytesEquals(int a, int b, int c, int d, byte[] actual) {
+ byte[] expected = new byte[] { (byte) a, (byte) b, (byte) c, (byte) d };
+ assertTrue("Expected " + Arrays.toString(expected) + ", got " + Arrays.toString(actual),
+ Arrays.equals(expected, actual));
+ }
+
+}
diff --git a/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java b/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java
new file mode 100644
index 0000000..d48d92a
--- /dev/null
+++ b/luni/src/test/java/libcore/sun/util/logging/PlatformLoggerTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.sun.util.logging;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.logging.Level;
+
+import sun.util.logging.PlatformLogger;
+
+public class PlatformLoggerTest extends TestCase {
+
+ /**
+ * Checks that the values of the private static final int constants in
+ * {@link PlatformLogger} code match the corresponding
+ * {@link Level#intValue()}. This constraint is mentioned in a comment
+ * in PlatformLogger.java.
+ */
+ public void testLogLevelConstants() throws Exception {
+ assertLogLevel("SEVERE", Level.SEVERE);
+ assertLogLevel("WARNING", Level.WARNING);
+ assertLogLevel("INFO", Level.INFO);
+ assertLogLevel("CONFIG", Level.CONFIG);
+ assertLogLevel("FINE", Level.FINE);
+ assertLogLevel("FINER", Level.FINER);
+ assertLogLevel("FINEST", Level.FINEST);
+ assertLogLevel("ALL", Level.ALL);
+ assertLogLevel("OFF", Level.OFF);
+ }
+
+ private void assertLogLevel(String levelName, Level javaUtilLoggingLevel) throws Exception {
+ Field field = PlatformLogger.class.getDeclaredField(levelName);
+ field.setAccessible(true);
+ int platformLoggerValue = field.getInt(PlatformLogger.class);
+ int javaUtilLoggingValue = javaUtilLoggingLevel.intValue();
+ assertEquals(levelName, javaUtilLoggingValue, platformLoggerValue);
+
+ // Check that the field is a constant (static and final); we don't care about
+ // other modifiers (public/private).
+ int requiredModifiers = Modifier.STATIC | Modifier.FINAL;
+ assertEquals(requiredModifiers, field.getModifiers() & requiredModifiers);
+ }
+
+}
diff --git a/ojluni/src/main/java/java/awt/font/TextAttribute.java b/ojluni/src/main/java/java/awt/font/TextAttribute.java
index 04a921d..7dff4ad 100644
--- a/ojluni/src/main/java/java/awt/font/TextAttribute.java
+++ b/ojluni/src/main/java/java/awt/font/TextAttribute.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -45,6 +45,8 @@
import java.util.Map;
import java.util.HashMap;
+// Android-removed: List of classes for use with attribute keys; Android doesn't have those.
+// Android-removed: "Summary of attributes" section. Android doesn't have the referenced classes.
/**
* The <code>TextAttribute</code> class defines attribute keys and
* attribute values used for text rendering.
@@ -62,7 +64,7 @@
* <LI>a description of the effect.
* </UL>
* <p>
- * <H4>Values</H4>
+ * <H3>Values</H3>
* <UL>
* <LI>The values of attributes must always be immutable.
* <LI>Where value limitations are given, any value outside of that
@@ -90,178 +92,12 @@
*
* </UL>
*
- * @see java.text.AttributedCharacterIterator
*/
-
-// Android-removed: Removed Summary of Attributes.
-/* <h4>Summary of attributes</h4>
- * <p>
- * <font size="-1">
- * <table align="center" border="0" cellspacing="0" cellpadding="2" width="%95"
- * summary="Key, value type, principal constants, and default value
- * behavior of all TextAttributes">
- * <tr bgcolor="#ccccff">
- * <th valign="TOP" align="CENTER">Key</th>
- * <th valign="TOP" align="CENTER">Value Type</th>
- * <th valign="TOP" align="CENTER">Principal Constants</th>
- * <th valign="TOP" align="CENTER">Default Value</th>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #FAMILY}</td>
- * <td valign="TOP">String</td>
- * <td valign="TOP">See Font {@link java.awt.Font#DIALOG DIALOG},
-{@link java.awt.Font#DIALOG_INPUT DIALOG_INPUT},<br> {@link java.awt.Font#SERIF SERIF},
-{@link java.awt.Font#SANS_SERIF SANS_SERIF}, and {@link java.awt.Font#MONOSPACED MONOSPACED}.
-</td>
- * <td valign="TOP">"Default" (use platform default)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #WEIGHT}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">WEIGHT_REGULAR, WEIGHT_BOLD</td>
- * <td valign="TOP">WEIGHT_REGULAR</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #WIDTH}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">WIDTH_CONDENSED, WIDTH_REGULAR,<br>WIDTH_EXTENDED</td>
- * <td valign="TOP">WIDTH_REGULAR</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #POSTURE}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">POSTURE_REGULAR, POSTURE_OBLIQUE</td>
- * <td valign="TOP">POSTURE_REGULAR</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SIZE}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">12.0</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #TRANSFORM}</td>
- * <td valign="TOP">{@link TransformAttribute}</td>
- * <td valign="TOP">See TransformAttribute {@link TransformAttribute#IDENTITY IDENTITY}</td>
- * <td valign="TOP">TransformAttribute.IDENTITY</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SUPERSCRIPT}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">SUPERSCRIPT_SUPER, SUPERSCRIPT_SUB</td>
- * <td valign="TOP">0 (use the standard glyphs and metrics)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #FONT}</td>
- * <td valign="TOP">{@link java.awt.Font}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not override font resolution)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #CHAR_REPLACEMENT}</td>
- * <td valign="TOP">{@link GraphicAttribute}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (draw text using font glyphs)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #FOREGROUND}</td>
- * <td valign="TOP">{@link java.awt.Paint}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (use current graphics paint)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #BACKGROUND}</td>
- * <td valign="TOP">{@link java.awt.Paint}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not render background)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #UNDERLINE}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">UNDERLINE_ON</td>
- * <td valign="TOP">-1 (do not render underline)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #STRIKETHROUGH}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">STRIKETHROUGH_ON</td>
- * <td valign="TOP">false (do not render strikethrough)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #RUN_DIRECTION}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">RUN_DIRECTION_LTR<br>RUN_DIRECTION_RTL</td>
- * <td valign="TOP">null (use {@link java.text.Bidi} standard default)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #BIDI_EMBEDDING}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">0 (use base line direction)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #JUSTIFICATION}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">JUSTIFICATION_FULL</td>
- * <td valign="TOP">JUSTIFICATION_FULL</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #INPUT_METHOD_HIGHLIGHT}</td>
- * <td valign="TOP">{@link java.awt.im.InputMethodHighlight},<br>{@link java.text.Annotation}</td>
- * <td valign="TOP">(see class)</td>
- * <td valign="TOP">null (do not apply input highlighting)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #INPUT_METHOD_UNDERLINE}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">UNDERLINE_LOW_ONE_PIXEL,<br>UNDERLINE_LOW_TWO_PIXEL</td>
- * <td valign="TOP">-1 (do not render underline)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #SWAP_COLORS}</td>
- * <td valign="TOP">Boolean</td>
- * <td valign="TOP">SWAP_COLORS_ON</td>
- * <td valign="TOP">false (do not swap colors)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #NUMERIC_SHAPING}</td>
- * <td valign="TOP">{@link java.awt.font.NumericShaper}</td>
- * <td valign="TOP">none</td>
- * <td valign="TOP">null (do not shape digits)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #KERNING}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">KERNING_ON</td>
- * <td valign="TOP">0 (do not request kerning)</td>
- * </tr>
- * <tr bgcolor="#eeeeff">
- * <td valign="TOP">{@link #LIGATURES}</td>
- * <td valign="TOP">Integer</td>
- * <td valign="TOP">LIGATURES_ON</td>
- * <td valign="TOP">0 (do not form optional ligatures)</td>
- * </tr>
- * <tr>
- * <td valign="TOP">{@link #TRACKING}</td>
- * <td valign="TOP">Number</td>
- * <td valign="TOP">TRACKING_LOOSE, TRACKING_TIGHT</td>
- * <td valign="TOP">0 (do not add tracking)</td>
- * </tr>
- * </table>
- * </font>
- *
- * @see java.awt.Font
- * @see java.awt.font.TextLayout
- */
-// Android-removed
-//
-// {@link java.awt.Font Font},
-// {@link java.awt.font.TextLayout TextLayout},
-// {@link java.text.AttributedCharacterIterator AttributedCharacterIterator},
public final class TextAttribute extends Attribute {
// table of all instances in this class, used by readResolve
- private static final Map instanceMap = new HashMap(29);
+ private static final Map<String, TextAttribute>
+ instanceMap = new HashMap<String, TextAttribute>(29);
/**
* Constructs a <code>TextAttribute</code> with the specified name.
@@ -284,7 +120,7 @@
"subclass didn't correctly implement readResolve");
}
- TextAttribute instance = (TextAttribute) instanceMap.get(getName());
+ TextAttribute instance = instanceMap.get(getName());
if (instance != null) {
return instance;
} else {
@@ -302,6 +138,7 @@
// For use with Font.
//
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key for the font name. Values are instances of
* <b><code>String</code></b>. The default value is
@@ -324,13 +161,6 @@
* The "Bold" in the name is part of the face name, not a separate
* request that the font's weight be bold.</p>
*/
- // Android-removed links to font names.
- //
- // {@link java.awt.Font#DIALOG DIALOG},
- // {@link java.awt.Font#DIALOG_INPUT DIALOG_INPUT},
- // {@link java.awt.Font#SANS_SERIF SANS_SERIF},
- // {@link java.awt.Font#SERIF SERIF}, and
- // {@link java.awt.Font#MONOSPACED MONOSPACED}.
public static final TextAttribute FAMILY =
new TextAttribute("family");
@@ -490,6 +320,7 @@
public static final Float WIDTH_EXTENDED =
Float.valueOf(1.5f);
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key for the posture of a font. Values are instances
* of <b><code>Number</code></b>. The default value is
@@ -510,8 +341,6 @@
* <code>Font.getItalicAngle</code>.
*
*/
- // Android-removed.
- // @see java.awt.Font#getItalicAngle()
public static final TextAttribute POSTURE =
new TextAttribute("posture");
@@ -548,6 +377,8 @@
public static final TextAttribute SIZE =
new TextAttribute("size");
+ // Android-removed: References to classes that don't exist on Android.
+ // These classes were AffineTransform, Font, and TransformAttribute.
/**
* Attribute key for the transform of a font. Values are
* instances of <b><code>TransformAttribute</code></b>. The
@@ -566,23 +397,6 @@
* with a rotated TRANSFORM and an unrotated TRANSFORM will measure as
* having the same ascent, descent, and advance.</p>
*/
- // Android-removed
- //
- // <p>This corresponds to the transform passed to
- // <code>Font.deriveFont(AffineTransform)</code>. Since that
- // transform is mutable and <code>TextAttribute</code> values must
- // not be, the <code>TransformAttribute</code> wrapper class is
- // used.
- //
- // <p>The <code>TransformAttribute</code> class defines the
- // constant {@link TransformAttribute#IDENTITY IDENTITY}.
- // @see TransformAttribute
- // @see java.awt.geom.AffineTransform
- //
- // <p>In styled text, the baselines for each such run are aligned
- // one after the other to potentially create a non-linear baseline
- // for the entire run of text. For more information, see {@link
- // TextLayout#getLayoutPath}.</p>
public static final TextAttribute TRANSFORM =
new TextAttribute("transform");
@@ -621,6 +435,7 @@
public static final Integer SUPERSCRIPT_SUB =
Integer.valueOf(-1);
+ // Android-removed: Don't link to java.awt.Font class, it doesn't exist on Android.
/**
* Attribute key used to provide the font to use to render text.
*
@@ -673,17 +488,6 @@
* <code>Font</code> but can be overridden by other values in the
* <code>Map</code>.
*/
- // Android-removed
- // Values are instances of {@link java.awt.Font}.
- //
- // <p><em>Note:</em><code>Font's</code> <code>Map</code>-based
- // constructor and <code>deriveFont</code> methods do not process
- // the <code>FONT</code> attribute, as these are used to create
- // new <code>Font</code> objects. Instead, {@link
- // java.awt.Font#getFont(Map) Font.getFont(Map)} should be used to
- // handle the <code>FONT</code> attribute.
- //
- // @see java.awt.Font
public static final TextAttribute FONT =
new TextAttribute("font");
@@ -900,6 +704,7 @@
// For use by input method.
//
+ // Android-removed: References to java.awt.im.InputMethodHighlight (doesn't exist on Android).
/**
* Attribute key for input method highlight styles.
*
@@ -909,24 +714,6 @@
*
* @see java.text.Annotation
*/
- // Android-removed
- //
- // <p>Values are instances of {@link
- // java.awt.im.InputMethodHighlight} or {@link
- // java.text.Annotation}.
- //
- // <p>If adjacent runs of text with the same
- // <code>InputMethodHighlight</code> need to be rendered
- // separately, the <code>InputMethodHighlights</code> should be
- // wrapped in <code>Annotation</code> instances.
- //
- // <p>Input method highlights are used while text is being
- // composed by an input method. Text editing components should
- // retain them even if they generally only deal with unstyled
- // text, and make them available to the drawing routines.
- //
- // @see java.awt.Font
- // @see java.awt.im.InputMethodHighlight
public static final TextAttribute INPUT_METHOD_HIGHLIGHT =
new TextAttribute("input method highlight");
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/ExpiringCache.java b/ojluni/src/main/java/java/io/ExpiringCache.java
index 02fd222..d0edb11 100644
--- a/ojluni/src/main/java/java/io/ExpiringCache.java
+++ b/ojluni/src/main/java/java/io/ExpiringCache.java
@@ -65,8 +65,12 @@
ExpiringCache(long millisUntilExpiration) {
this.millisUntilExpiration = millisUntilExpiration;
map = new LinkedHashMap<String,Entry>() {
- @Override
- protected boolean removeEldestEntry(Map.Entry eldest) {
+ // Android-changed: Qualified ExpiringCache.Entry to distinguish from Map.Entry.
+ // There seems to be a compiler difference between javac and jack here;
+ // Map.Entry<String,Entry> doesn't work on jack since the latter "Entry" gets
+ // interpreted as referring to Map.Entry rather than ExpiringCache.Entry.
+ // protected boolean removeEldestEntry(Map.Entry<String,Entry> eldest) {
+ protected boolean removeEldestEntry(Map.Entry<String,ExpiringCache.Entry> eldest) {
return size() > MAX_ENTRIES;
}
};
diff --git a/ojluni/src/main/java/java/io/FileDescriptor.java b/ojluni/src/main/java/java/io/FileDescriptor.java
index 7c82505..75f7388 100644
--- a/ojluni/src/main/java/java/io/FileDescriptor.java
+++ b/ojluni/src/main/java/java/io/FileDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -50,17 +50,19 @@
// the file descriptor.
public final class FileDescriptor {
+ // Android-changed: Renamed fd to descriptor to avoid issues with JNI/reflection
+ // fetching the descriptor value.
private int descriptor;
/**
* Constructs an (invalid) FileDescriptor
* object.
*/
- public FileDescriptor() {
+ public /* */ FileDescriptor() {
descriptor = -1;
}
- private FileDescriptor(int descriptor) {
+ private /* */ FileDescriptor(int descriptor) {
this.descriptor = descriptor;
}
@@ -71,6 +73,7 @@
*
* @see java.lang.System#in
*/
+ // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
public static final FileDescriptor in = dupFd(0);
/**
@@ -79,6 +82,7 @@
* known as <code>System.out</code>.
* @see java.lang.System#out
*/
+ // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
public static final FileDescriptor out = dupFd(1);
/**
@@ -88,6 +92,7 @@
*
* @see java.lang.System#err
*/
+ // Android-changed: Duplicates of FDs needed for RuntimeInit#redirectLogStreams
public static final FileDescriptor err = dupFd(2);
/**
@@ -131,12 +136,16 @@
*/
public native void sync() throws SyncFailedException;
+ // Android-removed: initIDs not used to allow compile-time intialization
+ /* This routine initializes JNI field offsets for the class */
+ //private static native void initIDs();
+
/**
* Returns the int descriptor. It's highly unlikely you should be calling this. Please discuss
* your needs with a libcore maintainer before using this method.
* @hide internal use only
*/
- // Android-added.
+ // Android-added: Needed for framework to access descriptor value
public final int getInt$() {
return descriptor;
}
@@ -146,7 +155,7 @@
* your needs with a libcore maintainer before using this method.
* @hide internal use only
*/
- // Android-added.
+ // Android-added: Needed for framework to access descriptor value
public final void setInt$(int fd) {
this.descriptor = fd;
}
@@ -154,12 +163,12 @@
/**
* @hide internal use only
*/
- // Android-added.
+ // Android-added: Needed for framework to test if it's a socket
public boolean isSocket$() {
return isSocket(descriptor);
}
- // Android-added.
+ // Android-added: Needed for RuntimeInit#redirectLogStreams.
private static FileDescriptor dupFd(int fd) {
try {
return new FileDescriptor(Os.fcntlInt(new FileDescriptor(fd), F_DUPFD_CLOEXEC, 0));
@@ -172,25 +181,24 @@
// Set up JavaIOFileDescriptorAccess in SharedSecrets
static {
sun.misc.SharedSecrets.setJavaIOFileDescriptorAccess(
- new sun.misc.JavaIOFileDescriptorAccess() {
- public void set(FileDescriptor obj, int fd) {
- obj.descriptor = fd;
- }
-
- public int get(FileDescriptor obj) {
- return obj.descriptor;
- }
-
- public void setHandle(FileDescriptor obj, long handle) {
- throw new UnsupportedOperationException();
- }
-
- public long getHandle(FileDescriptor obj) {
- throw new UnsupportedOperationException();
- }
+ new sun.misc.JavaIOFileDescriptorAccess() {
+ public void set(FileDescriptor obj, int fd) {
+ obj.descriptor = fd;
}
+
+ public int get(FileDescriptor obj) {
+ return obj.descriptor;
+ }
+
+ public void setHandle(FileDescriptor obj, long handle) {
+ throw new UnsupportedOperationException();
+ }
+
+ public long getHandle(FileDescriptor obj) {
+ throw new UnsupportedOperationException();
+ }
+ }
);
}
-
-
+// Android-removed: Removed method required for parents reference counting
}
diff --git a/ojluni/src/main/java/java/io/FilePermission.java b/ojluni/src/main/java/java/io/FilePermission.java
index 814a695..f9544c7 100644
--- a/ojluni/src/main/java/java/io/FilePermission.java
+++ b/ojluni/src/main/java/java/io/FilePermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/PrintStream.java b/ojluni/src/main/java/java/io/PrintStream.java
index 08bb3a3..809d39b 100644
--- a/ojluni/src/main/java/java/io/PrintStream.java
+++ b/ojluni/src/main/java/java/io/PrintStream.java
@@ -70,6 +70,7 @@
private BufferedWriter textOut;
private OutputStreamWriter charOut;
+ // Android-added: Lazy initialization of charOut and textOut.
private Charset charset;
/**
@@ -104,11 +105,18 @@
private PrintStream(boolean autoFlush, OutputStream out) {
super(out);
this.autoFlush = autoFlush;
+ // Android-changed: Lazy initialization of charOut and textOut.
+ // this.charOut = new OutputStreamWriter(this);
+ // this.textOut = new BufferedWriter(charOut);
}
private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
super(out);
this.autoFlush = autoFlush;
+ // Android-changed: Lazy initialization of charOut and textOut.
+ // this.charOut = new OutputStreamWriter(this, charset);
+ // this.textOut = new BufferedWriter(charOut);
+ this.charset = charset;
}
/* Variant of the private constructor so that the given charset name
@@ -344,7 +352,7 @@
private boolean closing = false; /* To avoid recursive closing */
- // Android-changed: Lazily initialize textOut.
+ // BEGIN Android-added: Lazy initialization of charOut and textOut.
private BufferedWriter getTextOut() {
if (textOut == null) {
charOut = charset != null ? new OutputStreamWriter(this, charset) :
@@ -353,6 +361,7 @@
}
return textOut;
}
+ // END Android-added: Lazy initialization of charOut and textOut.
/**
* Closes the stream. This is done by flushing the stream and then closing
@@ -365,10 +374,12 @@
if (! closing) {
closing = true;
try {
- // Android-changed: Lazily initialized.
+ // BEGIN Android-changed: Lazy initialization of charOut and textOut.
+ // textOut.close();
if (textOut != null) {
textOut.close();
}
+ // END Android-changed: Lazy initialization of charOut and textOut.
out.close();
}
catch (IOException x) {
@@ -512,7 +523,7 @@
try {
synchronized (this) {
ensureOpen();
- // Android-changed: Lazily initialized.
+ // Android-added: Lazy initialization of charOut and textOut.
BufferedWriter textOut = getTextOut();
textOut.write(buf);
textOut.flushBuffer();
@@ -536,7 +547,7 @@
try {
synchronized (this) {
ensureOpen();
- // Android-changed: Lazily initialized.
+ // Android-added: Lazy initialization of charOut and textOut.
BufferedWriter textOut = getTextOut();
textOut.write(s);
textOut.flushBuffer();
@@ -557,7 +568,7 @@
try {
synchronized (this) {
ensureOpen();
- // Android-changed: Lazily initialized.
+ // Android-added: Lazy initialization of charOut and textOut.
BufferedWriter textOut = getTextOut();
textOut.newLine();
textOut.flushBuffer();
diff --git a/ojluni/src/main/java/java/io/RandomAccessFile.java b/ojluni/src/main/java/java/io/RandomAccessFile.java
index 34eb7ab..f4830c1 100755
--- a/ojluni/src/main/java/java/io/RandomAccessFile.java
+++ b/ojluni/src/main/java/java/io/RandomAccessFile.java
@@ -65,10 +65,12 @@
public class RandomAccessFile implements DataOutput, DataInput, Closeable {
+ // BEGIN Android-added: CloseGuard and some helper fields for Android changes in this file.
private final CloseGuard guard = CloseGuard.get();
private final byte[] scratch = new byte[8];
private boolean syncMetadata = false;
private int mode;
+ // END Android-added: CloseGuard and some helper fields for Android changes in this file.
private FileDescriptor fd;
private FileChannel channel = null;
@@ -82,11 +84,14 @@
private Object closeLock = new Object();
private volatile boolean closed = false;
+
+ // BEGIN Android-added: IoTracker.
/**
* A single tracker to track both read and write. The tracker resets when the operation
* performed is different from the operation last performed.
*/
private final IoTracker ioTracker = new IoTracker();
+ // END Android-added: IoTracker.
/**
* Creates a random access file stream to read from, and optionally
@@ -216,43 +221,57 @@
throws FileNotFoundException
{
String name = (file != null ? file.getPath() : null);
- this.mode = -1;
+ int imode = -1;
if (mode.equals("r")) {
- this.mode = O_RDONLY;
+ imode = O_RDONLY;
} else if (mode.startsWith("rw")) {
// Android-changed: Added. O_CREAT
- this.mode = O_RDWR | O_CREAT;
+ // imode = O_RDWR;
+ imode = O_RDWR | O_CREAT;
rw = true;
if (mode.length() > 2) {
if (mode.equals("rws")) {
+ // Android-changed: Don't use O_SYNC for "rws". Is this correct?
+ // imode |= O_SYNC;
syncMetadata = true;
} else if (mode.equals("rwd")) {
- // Android-changed: Should this be O_DSYNC and the above O_SYNC ?
- this.mode |= O_SYNC;
+ // Android-changed: Use O_SYNC rather than O_DSYNC for "rwd". Is this correct?
+ // imode |= O_DSYNC;
+ imode |= O_SYNC;
} else {
- this.mode = -1;
+ imode = -1;
}
}
}
-
- if (this.mode < 0) {
+ if (imode < 0) {
throw new IllegalArgumentException("Illegal mode \"" + mode
+ "\" must be one of "
+ "\"r\", \"rw\", \"rws\","
+ " or \"rwd\"");
}
-
+ // Android-removed: do not use legacy security code
+ /*
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ security.checkRead(name);
+ if (rw) {
+ security.checkWrite(name);
+ }
+ }
+ */
if (name == null) {
+ // Android-changed: different exception message in ctor when file == null.
+ // throw new NullPointerException();
throw new NullPointerException("file == null");
}
-
if (file.isInvalid()) {
throw new FileNotFoundException("Invalid file path");
}
this.path = name;
+ this.mode = imode;
- // Android-changed: Use IoBridge.open() instead of open.
- fd = IoBridge.open(file.getPath(), this.mode);
+ // BEGIN Android-changed: Use IoBridge.open() instead of open.
+ fd = IoBridge.open(name, imode);
if (syncMetadata) {
try {
fd.sync();
@@ -261,6 +280,7 @@
}
}
guard.open("close");
+ // END Android-changed: Use IoBridge.open() instead of open.
}
/**
@@ -321,6 +341,8 @@
* end-of-file has been reached.
*/
public int read() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // return read0();
return (read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
}
@@ -332,6 +354,7 @@
* @exception IOException If an I/O error has occurred.
*/
private int readBytes(byte b[], int off, int len) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
ioTracker.trackIo(len, IoTracker.Mode.READ);
return IoBridge.read(fd, b, off, len);
}
@@ -474,6 +497,8 @@
* @exception IOException if an I/O error occurs.
*/
public void write(int b) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // write0(b);
scratch[0] = (byte) (b & 0xff);
write(scratch, 0, 1);
}
@@ -481,11 +506,13 @@
/**
* Writes a sub array as a sequence of bytes.
* @param b the data to be written
+
* @param off the start offset in the data
* @param len the number of bytes that are written
* @exception IOException If an I/O error has occurred.
*/
private void writeBytes(byte b[], int off, int len) throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
ioTracker.trackIo(len, IoTracker.Mode.WRITE);
IoBridge.write(fd, b, off, len);
// if we are in "rws" mode, attempt to sync file+metadata
@@ -528,6 +555,7 @@
* @exception IOException if an I/O error occurs.
*/
public long getFilePointer() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
try {
return Libcore.os.lseek(fd, 0L, SEEK_CUR);
} catch (ErrnoException errnoException) {
@@ -543,21 +571,26 @@
* change only by writing after the offset has been set beyond the end
* of the file.
*
- * @param offset the offset position, measured in bytes from the
+ * @param pos the offset position, measured in bytes from the
* beginning of the file, at which to set the file
* pointer.
* @exception IOException if {@code pos} is less than
* {@code 0} or if an I/O error occurs.
*/
- public void seek(long offset) throws IOException {
- if (offset < 0) {
- throw new IOException("offset < 0: " + offset);
- }
- try {
- Libcore.os.lseek(fd, offset, SEEK_SET);
- ioTracker.reset();
- } catch (ErrnoException errnoException) {
- throw errnoException.rethrowAsIOException();
+ public void seek(long pos) throws IOException {
+ if (pos < 0) {
+ // Android-changed: different exception message for seek(-1).
+ // throw new IOException("Negative seek offset");
+ throw new IOException("offset < 0: " + pos);
+ } else {
+ // Android-changed: Implement on top of low-level API, not directly natively.
+ // seek0(pos);
+ try {
+ Libcore.os.lseek(fd, pos, SEEK_SET);
+ ioTracker.reset();
+ } catch (ErrnoException errnoException) {
+ throw errnoException.rethrowAsIOException();
+ }
}
}
@@ -568,6 +601,7 @@
* @exception IOException if an I/O error occurs.
*/
public long length() throws IOException {
+ // Android-changed: Implement on top of low-level API, not directly natively.
try {
return Libcore.os.fstat(fd).st_size;
} catch (ErrnoException errnoException) {
@@ -595,6 +629,7 @@
* @since 1.2
*/
public void setLength(long newLength) throws IOException {
+ // BEGIN Android-changed: Implement on top of low-level API, not directly natively.
if (newLength < 0) {
throw new IllegalArgumentException("newLength < 0");
}
@@ -612,6 +647,7 @@
if (syncMetadata) {
fd.sync();
}
+ // END Android-changed: Implement on top of low-level API, not directly natively.
}
@@ -638,10 +674,12 @@
closed = true;
}
+ // BEGIN Android-changed: Implement on top of low-level API, not directly natively.
if (channel != null && channel.isOpen()) {
channel.close();
}
IoBridge.closeAndSignalBlockedThreads(fd);
+ // END Android-changed: Implement on top of low-level API, not directly natively.
}
//
@@ -1166,6 +1204,7 @@
DataOutputStream.writeUTF(str, this);
}
+ // Android-added: use finalize() to detect if not close()d.
@Override protected void finalize() throws Throwable {
try {
if (guard != null) {
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/Class.java b/ojluni/src/main/java/java/lang/Class.java
index 3717cd7..ed9f915 100644
--- a/ojluni/src/main/java/java/lang/Class.java
+++ b/ojluni/src/main/java/java/lang/Class.java
@@ -2403,13 +2403,15 @@
return (values != null) ? values.clone() : null;
}
+ // Android-changed: Made public/hidden instead of using sun.misc.SharedSecrets.
/**
* Returns the elements of this enum class or null if this
* Class object does not represent an enum type;
* identical to getEnumConstants except that the result is
* uncloned, cached, and shared by all callers.
+ * @hide
*/
- T[] getEnumConstantsShared() {
+ public T[] getEnumConstantsShared() {
if (!isEnum()) return null;
return (T[]) Enum.getSharedConstants((Class) this);
}
diff --git a/ojluni/src/main/java/java/lang/JavaLangAccess.java b/ojluni/src/main/java/java/lang/JavaLangAccess.java
deleted file mode 100644
index 2779c60..0000000
--- a/ojluni/src/main/java/java/lang/JavaLangAccess.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2003, 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.
- */
-
-package java.lang;
-
-/**
- * @hide
- */
-public final class JavaLangAccess {
- private JavaLangAccess() {
- }
-
- /**
- * @hide
- */
- public static <E extends Enum<E>>
- E[] getEnumConstantsShared(Class<E> klass) {
- return klass.getEnumConstantsShared();
- }
-}
diff --git a/ojluni/src/main/java/java/lang/RuntimePermission.java b/ojluni/src/main/java/java/lang/RuntimePermission.java
index 19dff55..2d05ba1 100644
--- a/ojluni/src/main/java/java/lang/RuntimePermission.java
+++ b/ojluni/src/main/java/java/lang/RuntimePermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/lang/SecurityManager.java b/ojluni/src/main/java/java/lang/SecurityManager.java
index 0cf702e..b7053e0 100644
--- a/ojluni/src/main/java/java/lang/SecurityManager.java
+++ b/ojluni/src/main/java/java/lang/SecurityManager.java
@@ -30,6 +30,10 @@
import java.io.FileDescriptor;
import java.net.InetAddress;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// SecurityManager can only check access by Java code, so it can be bypassed by using
+// native code. Applications should rely on Android permissions, process separation,
+// other other methods for security purposes.
/**
* Legacy security code; do not 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/ref/Reference.java b/ojluni/src/main/java/java/lang/ref/Reference.java
index 99adb36..d628fab 100644
--- a/ojluni/src/main/java/java/lang/ref/Reference.java
+++ b/ojluni/src/main/java/java/lang/ref/Reference.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
diff --git a/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java b/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
index 96a2d21..a5e5be1 100644
--- a/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
+++ b/ojluni/src/main/java/java/lang/reflect/ReflectPermission.java
@@ -25,6 +25,8 @@
package java.lang.reflect;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/NetPermission.java b/ojluni/src/main/java/java/net/NetPermission.java
index 8eb7892..b5a0eab 100644
--- a/ojluni/src/main/java/java/net/NetPermission.java
+++ b/ojluni/src/main/java/java/net/NetPermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/SocketPermission.java b/ojluni/src/main/java/java/net/SocketPermission.java
index cdd9f15..2195ecc 100644
--- a/ojluni/src/main/java/java/net/SocketPermission.java
+++ b/ojluni/src/main/java/java/net/SocketPermission.java
@@ -28,6 +28,8 @@
import java.security.Permission;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/net/URLClassLoader.java b/ojluni/src/main/java/java/net/URLClassLoader.java
index 226492d..edb9b88 100644
--- a/ojluni/src/main/java/java/net/URLClassLoader.java
+++ b/ojluni/src/main/java/java/net/URLClassLoader.java
@@ -190,8 +190,8 @@
if (security != null) {
security.checkCreateClassLoader();
}
- ucp = new URLClassPath(urls, factory);
acc = AccessController.getContext();
+ ucp = new URLClassPath(urls, factory, acc);
}
/* A map (used as a set) to keep track of closeable local resources
diff --git a/ojluni/src/main/java/java/security/AccessControlContext.java b/ojluni/src/main/java/java/security/AccessControlContext.java
index e95cff2..506898f 100644
--- a/ojluni/src/main/java/java/security/AccessControlContext.java
+++ b/ojluni/src/main/java/java/security/AccessControlContext.java
@@ -30,6 +30,8 @@
import java.util.List;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/AccessController.java b/ojluni/src/main/java/java/security/AccessController.java
index b4d544c..ad844ba 100644
--- a/ojluni/src/main/java/java/security/AccessController.java
+++ b/ojluni/src/main/java/java/security/AccessController.java
@@ -27,6 +27,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/AllPermission.java b/ojluni/src/main/java/java/security/AllPermission.java
index 20e452b..61bcaea 100644
--- a/ojluni/src/main/java/java/security/AllPermission.java
+++ b/ojluni/src/main/java/java/security/AllPermission.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/AuthProvider.java b/ojluni/src/main/java/java/security/AuthProvider.java
index 23ddb0a..e87daa9 100644
--- a/ojluni/src/main/java/java/security/AuthProvider.java
+++ b/ojluni/src/main/java/java/security/AuthProvider.java
@@ -29,6 +29,8 @@
import javax.security.auth.login.LoginException;
import javax.security.auth.callback.CallbackHandler;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/BasicPermission.java b/ojluni/src/main/java/java/security/BasicPermission.java
index 0a069b0..1836b10 100644
--- a/ojluni/src/main/java/java/security/BasicPermission.java
+++ b/ojluni/src/main/java/java/security/BasicPermission.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/CodeSource.java b/ojluni/src/main/java/java/security/CodeSource.java
index 7396d91..fce8aa1 100644
--- a/ojluni/src/main/java/java/security/CodeSource.java
+++ b/ojluni/src/main/java/java/security/CodeSource.java
@@ -35,6 +35,8 @@
import java.io.IOException;
import java.security.cert.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/DomainCombiner.java b/ojluni/src/main/java/java/security/DomainCombiner.java
index 5426bf6..e9c010f 100644
--- a/ojluni/src/main/java/java/security/DomainCombiner.java
+++ b/ojluni/src/main/java/java/security/DomainCombiner.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/IdentityScope.java b/ojluni/src/main/java/java/security/IdentityScope.java
index 65f4e98..61d37cb 100644
--- a/ojluni/src/main/java/java/security/IdentityScope.java
+++ b/ojluni/src/main/java/java/security/IdentityScope.java
@@ -87,6 +87,8 @@
} else {
try {
+ // Android-changed: Actually set the system scope after initializing it
+ // Class.forName(classname);
scope = (IdentityScope) Class.forName(classname).newInstance();
} catch (Exception e) {
//Security.error("unable to establish a system scope from " +
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/KeyStoreSpi.java b/ojluni/src/main/java/java/security/KeyStoreSpi.java
index 4caa59c..531a983 100644
--- a/ojluni/src/main/java/java/security/KeyStoreSpi.java
+++ b/ojluni/src/main/java/java/security/KeyStoreSpi.java
@@ -34,6 +34,7 @@
import java.security.cert.CertificateException;
import javax.crypto.SecretKey;
+
import javax.security.auth.callback.*;
/**
@@ -451,34 +452,43 @@
return null;
}
- if (protParam != null &&
- !(protParam instanceof KeyStore.PasswordProtection)) {
- throw new UnsupportedOperationException();
+ if (protParam == null) {
+ if (engineIsCertificateEntry(alias)) {
+ return new KeyStore.TrustedCertificateEntry
+ (engineGetCertificate(alias));
+ // Android-removed: Allow access to entries with no password.
+ // } else {
+ // throw new UnrecoverableKeyException
+ // ("requested entry requires a password");
+ }
}
- if (engineIsCertificateEntry(alias)) {
- if (protParam == null) {
- return new KeyStore.TrustedCertificateEntry
- (engineGetCertificate(alias));
- } else {
+ // Android-changed: Add protParam == null to allow access to entries with no password.
+ if ((protParam == null) || protParam instanceof KeyStore.PasswordProtection) {
+ if (engineIsCertificateEntry(alias)) {
throw new UnsupportedOperationException
("trusted certificate entries are not password-protected");
+ } else if (engineIsKeyEntry(alias)) {
+ // Android-changed: Allow access to entries with no password.
+ // KeyStore.PasswordProtection pp =
+ // (KeyStore.PasswordProtection)protParam;
+ // char[] password = pp.getPassword();
+ char[] password = null;
+ if (protParam != null) {
+ KeyStore.PasswordProtection pp =
+ (KeyStore.PasswordProtection)protParam;
+ password = pp.getPassword();
+ }
+ Key key = engineGetKey(alias, password);
+ if (key instanceof PrivateKey) {
+ Certificate[] chain = engineGetCertificateChain(alias);
+ return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain);
+ } else if (key instanceof SecretKey) {
+ return new KeyStore.SecretKeyEntry((SecretKey)key);
+ }
}
- } else if (engineIsKeyEntry(alias)) {
- char[] password = null;
- if (protParam != null) {
- KeyStore.PasswordProtection pp =
- (KeyStore.PasswordProtection)protParam;
- password = pp.getPassword();
- }
- Key key = engineGetKey(alias, password);
- if (key instanceof PrivateKey) {
- Certificate[] chain = engineGetCertificateChain(alias);
- return new KeyStore.PrivateKeyEntry((PrivateKey)key, chain);
- } else if (key instanceof SecretKey) {
- return new KeyStore.SecretKeyEntry((SecretKey)key);
- }
}
+
throw new UnsupportedOperationException();
}
@@ -514,6 +524,7 @@
pProtect = (KeyStore.PasswordProtection)protParam;
}
+ // BEGIN Android-changed: Allow access to entries with no password.
char[] password = (pProtect == null) ? null : pProtect.getPassword();
// set entry
if (entry instanceof KeyStore.TrustedCertificateEntry) {
@@ -536,6 +547,7 @@
(Certificate[])null);
return;
}
+ // END Android-changed: Allow access to entries with no password.
throw new KeyStoreException
("unsupported entry type: " + entry.getClass().getName());
diff --git a/ojluni/src/main/java/java/security/MessageDigest.java b/ojluni/src/main/java/java/security/MessageDigest.java
index df6c456..8e5dab1 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());
@@ -450,6 +446,7 @@
* Returns a string representation of this message digest object.
*/
public String toString() {
+ // BEGIN Android-changed: Use StringBuilder instead of a ByteArrayOutputStream.
StringBuilder builder = new StringBuilder();
builder.append(algorithm);
builder.append(" Message Digest from ");
@@ -466,6 +463,7 @@
}
return builder.toString();
+ // END Android-changed: Use StringBuilder instead of a ByteArrayOutputStream.
}
/**
diff --git a/ojluni/src/main/java/java/security/Permission.java b/ojluni/src/main/java/java/security/Permission.java
index 8d170c0..54163b9 100644
--- a/ojluni/src/main/java/java/security/Permission.java
+++ b/ojluni/src/main/java/java/security/Permission.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/PermissionCollection.java b/ojluni/src/main/java/java/security/PermissionCollection.java
index e356524..f1015e3 100644
--- a/ojluni/src/main/java/java/security/PermissionCollection.java
+++ b/ojluni/src/main/java/java/security/PermissionCollection.java
@@ -27,6 +27,8 @@
import java.util.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/Permissions.java b/ojluni/src/main/java/java/security/Permissions.java
index 7411e06..9796f01 100644
--- a/ojluni/src/main/java/java/security/Permissions.java
+++ b/ojluni/src/main/java/java/security/Permissions.java
@@ -29,6 +29,8 @@
import java.io.Serializable;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/Policy.java b/ojluni/src/main/java/java/security/Policy.java
index 71c6cd0..cb7fb3b 100644
--- a/ojluni/src/main/java/java/security/Policy.java
+++ b/ojluni/src/main/java/java/security/Policy.java
@@ -29,9 +29,8 @@
import java.util.Enumeration;
-
-/* Not used on Android, removed most of the code and made the class methods no-ops */
-
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/PrivilegedAction.java b/ojluni/src/main/java/java/security/PrivilegedAction.java
index bef7e44..5844b4d 100644
--- a/ojluni/src/main/java/java/security/PrivilegedAction.java
+++ b/ojluni/src/main/java/java/security/PrivilegedAction.java
@@ -26,6 +26,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/PrivilegedActionException.java b/ojluni/src/main/java/java/security/PrivilegedActionException.java
index 83d855a..b1eb28f 100644
--- a/ojluni/src/main/java/java/security/PrivilegedActionException.java
+++ b/ojluni/src/main/java/java/security/PrivilegedActionException.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*
diff --git a/ojluni/src/main/java/java/security/PrivilegedExceptionAction.java b/ojluni/src/main/java/java/security/PrivilegedExceptionAction.java
index bae883e..4023150 100644
--- a/ojluni/src/main/java/java/security/PrivilegedExceptionAction.java
+++ b/ojluni/src/main/java/java/security/PrivilegedExceptionAction.java
@@ -26,6 +26,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/ProtectionDomain.java b/ojluni/src/main/java/java/security/ProtectionDomain.java
index 7cacc35..9e117a6 100644
--- a/ojluni/src/main/java/java/security/ProtectionDomain.java
+++ b/ojluni/src/main/java/java/security/ProtectionDomain.java
@@ -26,6 +26,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/Provider.java b/ojluni/src/main/java/java/security/Provider.java
index d1fbd29..cbf37db 100644
--- a/ojluni/src/main/java/java/security/Provider.java
+++ b/ojluni/src/main/java/java/security/Provider.java
@@ -95,6 +95,10 @@
// Declare serialVersionUID to be compatible with JDK1.1
static final long serialVersionUID = -4298000515446427739L;
+ // Android-added: Provider registration
+ // Marking a provider as "registered" makes it change the security version when
+ // changes to it are made. As of 2017-05-22 this is only used in ProviderTest.
+ // TODO: Change ProviderTest to no longer require this mechanism
private volatile boolean registered = false;
private static final sun.security.util.Debug debug =
@@ -699,6 +703,7 @@
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
+ // Android-added: Provider registration
registered = false;
Map<Object,Object> copy = new HashMap<>();
for (Map.Entry<Object,Object> entry : super.entrySet()) {
@@ -712,6 +717,7 @@
}
private boolean checkLegacy(Object key) {
+ // Android-added: Provider registration
if (registered) {
Security.increaseVersion();
}
@@ -736,6 +742,7 @@
for (Map.Entry<?,?> e : t.entrySet()) {
implPut(e.getKey(), e.getValue());
}
+ // Android-added: Provider registration
if (registered) {
Security.increaseVersion();
}
@@ -879,6 +886,7 @@
serviceSet = null;
super.clear();
putId();
+ // Android-added: Provider registration
if (registered) {
Security.increaseVersion();
}
@@ -1183,6 +1191,7 @@
String key = type + "." + algorithm + " " + entry.getKey();
super.put(key, entry.getValue());
}
+ // Android-added: Provider registration
if (registered) {
Security.increaseVersion();
}
@@ -1204,6 +1213,7 @@
String key = type + "." + algorithm + " " + entry.getKey();
super.remove(key);
}
+ // Android-added: Provider registration
if (registered) {
Security.increaseVersion();
}
@@ -1872,6 +1882,7 @@
}
+ // BEGIN Android-added: Provider registration
/**
* @hide
*/
@@ -1910,4 +1921,5 @@
// stored field, if the services didn't change in the meantime.
getServices();
}
+ // END Android-added: Provider registration
}
diff --git a/ojluni/src/main/java/java/security/SecureRandom.java b/ojluni/src/main/java/java/security/SecureRandom.java
index 78eac68..0852cbd 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");
@@ -203,7 +203,7 @@
private void getDefaultPRNG(boolean setSeed, byte[] seed) {
String prng = getPrngAlgorithm();
if (prng == null) {
- // Android-changed, should never happen
+ // Android-changed: This should never happen, we always provide a SecureRandom
throw new IllegalStateException("No SecureRandom implementation!");
} else {
try {
@@ -300,6 +300,7 @@
instance.provider, algorithm);
}
+ // BEGIN Android-added: Support for Crypto provider workaround
/**
* Maximum SDK version for which the workaround for the Crypto provider is in place.
*
@@ -332,6 +333,7 @@
public static int getSdkTargetForCryptoProviderWorkaround() {
return sdkTargetForCryptoProviderWorkaround;
}
+ // END Android-added: Support for Crypto provider workaround
/**
* Returns a SecureRandom object that implements the specified
@@ -383,6 +385,7 @@
SecureRandomSpi.class, algorithm, provider);
return new SecureRandom((SecureRandomSpi) instance.impl,
instance.provider, algorithm);
+ // BEGIN Android-added: Crypto provider deprecation
} catch (NoSuchProviderException nspe) {
if ("Crypto".equals(provider)) {
System.logE(" ********** PLEASE READ ************ ");
@@ -424,6 +427,7 @@
return new SecureRandom(
(SecureRandomSpi) instance.impl, instance.provider, algorithm);
}
+ // END Android-added: Crypto provider deprecation
/**
* Returns a SecureRandom object that implements the specified
@@ -547,6 +551,9 @@
* @param bytes the array to be filled in with random bytes.
*/
@Override
+ // Android-changed: Added synchronized
+ // This method has been synchronized at least since Cupcake, so it would probably
+ // lead to problems if it was removed.
synchronized public void nextBytes(byte[] bytes) {
secureRandomSpi.engineNextBytes(bytes);
}
@@ -695,6 +702,7 @@
*/
public static SecureRandom getInstanceStrong()
throws NoSuchAlgorithmException {
+
String property = AccessController.doPrivileged(
new PrivilegedAction<String>() {
@Override
diff --git a/ojluni/src/main/java/java/security/Security.java b/ojluni/src/main/java/java/security/Security.java
index dc248eb..743cf36 100644
--- a/ojluni/src/main/java/java/security/Security.java
+++ b/ojluni/src/main/java/java/security/Security.java
@@ -48,9 +48,16 @@
public final class Security {
+ // Android-added: Track the version to allow callers know when something has changed.
private static final AtomicInteger version = new AtomicInteger();
+ // Android-removed: Debug is stubbed and disabled on Android.
+ // /* Are we debugging? -- for developers */
+ // private static final Debug sdebug =
+ // Debug.getInstance("properties");
+
/* The java.security properties */
+ // Android-changed: Added final.
private static final Properties props;
// An element in the cache
@@ -60,12 +67,31 @@
}
static {
+// BEGIN Android-changed: doPrivileged is stubbed on Android.
+// Also, because props is final it must be assigned in the static block, not a method.
+ /*
+ // doPrivileged here because there are multiple
+ // things in initialize that might require privs.
+ // (the FileInputStream call and the File.exists call,
+ // the securityPropFile call, etc)
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ initialize();
+ return null;
+ }
+ });
+ }
+
+ private static void initialize() {
+ */
+// END Android-changed: doPrivileged is stubbed on Android.
props = new Properties();
boolean loadedProps = false;
+ // BEGIN Android-changed: Use a resource file, Android logging, and only one file.
InputStream is = null;
try {
/*
- * Android keeps the property file in a jar resource.
+ * Android keeps the property file in a resource file.
*/
InputStream propStream = Security.class.getResourceAsStream("security.properties");
if (propStream == null) {
@@ -84,6 +110,7 @@
} catch (IOException ignored) {}
}
}
+ // END Android-changed: Use a resource file, Android logging, and only one file.
if (!loadedProps) {
initializeStatic();
@@ -95,6 +122,15 @@
* is not found.
*/
private static void initializeStatic() {
+ // Android-changed: Use Conscrypt and BC, not the sun.security providers.
+ /*
+ props.put("security.provider.1", "sun.security.provider.Sun");
+ props.put("security.provider.2", "sun.security.rsa.SunRsaSign");
+ props.put("security.provider.3", "com.sun.net.ssl.internal.ssl.Provider");
+ props.put("security.provider.4", "com.sun.crypto.provider.SunJCE");
+ props.put("security.provider.5", "sun.security.jgss.SunProvider");
+ props.put("security.provider.6", "com.sun.security.sasl.Provider");
+ */
props.put("security.provider.1", "com.android.org.conscrypt.OpenSSLProvider");
props.put("security.provider.2", "sun.security.provider.CertPathProvider");
props.put("security.provider.3", "com.android.org.bouncycastle.jce.provider.BouncyCastleProvider");
@@ -247,15 +283,14 @@
public static synchronized int insertProviderAt(Provider provider,
int position) {
String providerName = provider.getName();
- // Android-removed
- // Checks using SecurityManager, which is not functional in Android.
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
// checkInsertProvider(providerName);
- // Android-removed
ProviderList list = Providers.getFullProviderList();
ProviderList newList = ProviderList.insertAt(list, provider, position - 1);
if (list == newList) {
return -1;
}
+ // Android-added: Version tracking call.
increaseVersion();
Providers.setProviderList(newList);
return newList.getIndex(providerName) + 1;
@@ -331,10 +366,12 @@
* @see #addProvider
*/
public static synchronized void removeProvider(String name) {
- check("removeProvider." + name);
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
+ // check("removeProvider." + name);
ProviderList list = Providers.getFullProviderList();
ProviderList newList = ProviderList.remove(list, name);
Providers.setProviderList(newList);
+ // Android-added: Version tracking call.
increaseVersion();
}
@@ -685,8 +722,10 @@
* @see java.security.SecurityPermission
*/
public static void setProperty(String key, String datum) {
- check("setProperty."+key);
+ // Android-removed: Checks using SecurityManager, which is not functional in Android.
+ // check("setProperty."+key);
props.put(key, datum);
+ // Android-added: Version tracking call.
increaseVersion();
invalidateSMCache(key); /* See below. */
}
@@ -745,6 +784,8 @@
} /* if */
}
+ // BEGIN Android-removed: SecurityManager is stubbed on Android.
+ /*
private static void check(String directive) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
@@ -752,6 +793,25 @@
}
}
+ private static void checkInsertProvider(String name) {
+ SecurityManager security = System.getSecurityManager();
+ if (security != null) {
+ try {
+ security.checkSecurityAccess("insertProvider");
+ } catch (SecurityException se1) {
+ try {
+ security.checkSecurityAccess("insertProvider." + name);
+ } catch (SecurityException se2) {
+ // throw first exception, but add second to suppressed
+ se1.addSuppressed(se2);
+ throw se1;
+ }
+ }
+ }
+ }
+ */
+ // END Android-removed: SecurityManager is stubbed on Android.
+
/*
* Returns all providers who satisfy the specified
* criterion.
@@ -1004,6 +1064,7 @@
return Collections.unmodifiableSet(result);
}
+ // BEGIN Android-added: Methods for version handling.
/**
* @hide
*/
@@ -1016,4 +1077,5 @@
public static int getVersion() {
return version.get();
}
+ // END Android-added: Methods for version handling.
}
diff --git a/ojluni/src/main/java/java/security/SecurityPermission.java b/ojluni/src/main/java/java/security/SecurityPermission.java
index 7d2ec47..f02755c 100644
--- a/ojluni/src/main/java/java/security/SecurityPermission.java
+++ b/ojluni/src/main/java/java/security/SecurityPermission.java
@@ -25,6 +25,8 @@
package java.security;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/Signature.java b/ojluni/src/main/java/java/security/Signature.java
index 7e9f5a8..5a0e6a8 100644
--- a/ojluni/src/main/java/java/security/Signature.java
+++ b/ojluni/src/main/java/java/security/Signature.java
@@ -368,6 +368,8 @@
do {
Service s = t.next();
if (isSpi(s)) {
+ // Android-changed: Delegate constructor only takes algorithm.
+ // return new Delegate(s, t, algorithm);
return new Delegate(algorithm);
} else {
// must be a subclass of Signature, disable dynamic selection
@@ -1064,7 +1066,7 @@
* @deprecated Deprecated.
*/
@Deprecated
- // Android-changed add "Deprecated."
+ // Android-changed: add "Deprecated."
public final Object getParameter(String param)
throws InvalidParameterException {
return engineGetParameter(param);
@@ -1086,6 +1088,7 @@
}
}
+ // BEGIN Android-added: Allow access to the current SPI for testing purposes.
/**
* Returns the {@code SignatureSpi} backing this {@code Signature}.
*
@@ -1094,6 +1097,7 @@
public SignatureSpi getCurrentSpi() {
return null;
}
+ // END Android-added: Allow access to the current SPI for testing purposes.
/*
* The following class allows providers to extend from SignatureSpi
@@ -1114,25 +1118,43 @@
// The provider implementation (delegate)
// filled in once the provider is selected
- // BEGIN Android-added
+ // BEGIN Android-note: Note on sigSpi invariants.
// (Not necessarily Android specific)
// Invariant to be preserved: sigSpi cannot be changed once it was assigned to something
- // different than null and lock is null. That is the case when sigSpi is specified in the
- // constructor.
- // END Android-added
+ // different than null and lock is null. That is only the case when sigSpi is specified
+ // in the constructor.
+ // END Android-note: Note on sigSpi invariants.
private SignatureSpi sigSpi;
// lock for mutex during provider selection
private final Object lock;
+ // BEGIN Android-removed: Redo the provider selection logic to allow reselecting provider.
+ // When only the algorithm is specified, we want to allow the Signature provider for that
+ // algorithm to change if multiple providers exist and they support different subsets of
+ // keys. To that end, we don't hold an iterator and exhaust it when we need to choose
+ // a provider like the upstream implementation, we reestablish the list of providers
+ // each time.
+ /*
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator<Service> serviceIterator;
+ */
+ // END Android-removed: Redo the provider selection logic to allow reselecting provider.
+
// constructor
Delegate(SignatureSpi sigSpi, String algorithm) {
super(algorithm);
this.sigSpi = sigSpi;
- this.lock = null;
+ this.lock = null; // no lock needed
}
// used with delayed provider selection
+ // Android-changed: Remove Service and Iterator from constructor args.
Delegate(String algorithm) {
super(algorithm);
this.lock = new Object();
@@ -1215,6 +1237,7 @@
*/
// END Android-removed: this debugging mechanism is not supported in Android.
Exception lastException = null;
+// BEGIN Android-changed: Provider selection; loop over a new list each time.
List<Service> list;
if (((Signature)this).algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
list = GetInstance.getServices(rsaIds);
@@ -1223,12 +1246,19 @@
((Signature)this).algorithm);
}
for (Service s : list) {
+// END Android-changed: Provider selection; loop over a new list each time.
if (isSpi(s) == false) {
continue;
}
try {
sigSpi = newInstance(s);
provider = s.getProvider();
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (NoSuchAlgorithmException e) {
lastException = e;
@@ -1246,11 +1276,14 @@
private void chooseProvider(int type, Key key, SecureRandom random)
throws InvalidKeyException {
synchronized (lock) {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
if (sigSpi != null && key == null) {
init(sigSpi, type, key, random);
return;
}
Exception lastException = null;
+// BEGIN Android-changed: Provider selection; loop over a new list each time.
List<Service> list;
if (((Signature)this).algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
list = GetInstance.getServices(rsaIds);
@@ -1259,6 +1292,7 @@
((Signature)this).algorithm);
}
for (Service s : list) {
+// END Android-changed: Provider selection; loop over a new list each time.
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
continue;
@@ -1272,6 +1306,11 @@
init(spi, type, key, random);
provider = s.getProvider();
sigSpi = spi;
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
@@ -1280,6 +1319,7 @@
if (lastException == null) {
lastException = e;
}
+ // Android-added: Throw InvalidKeyException immediately.
if (lastException instanceof InvalidKeyException) {
throw (InvalidKeyException)lastException;
}
@@ -1322,6 +1362,8 @@
protected void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
if (sigSpi != null && (lock == null || publicKey == null)) {
sigSpi.engineInitVerify(publicKey);
} else {
@@ -1331,6 +1373,8 @@
protected void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
if (sigSpi != null && (lock == null || privateKey == null)) {
sigSpi.engineInitSign(privateKey);
} else {
@@ -1340,6 +1384,8 @@
protected void engineInitSign(PrivateKey privateKey, SecureRandom sr)
throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (sigSpi != null) {
if (sigSpi != null && (lock == null || privateKey == null)) {
sigSpi.engineInitSign(privateKey, sr);
} else {
@@ -1409,6 +1455,7 @@
return sigSpi.engineGetParameters();
}
+ // BEGIN Android-added: Allow access to the current SPI for testing purposes.
@Override
public SignatureSpi getCurrentSpi() {
if (lock == null) {
@@ -1418,6 +1465,7 @@
return sigSpi;
}
}
+ // END Android-added: Allow access to the current SPI for testing purposes.
}
// adapter for RSA/ECB/PKCS1Padding ciphers
diff --git a/ojluni/src/main/java/java/security/UnresolvedPermission.java b/ojluni/src/main/java/java/security/UnresolvedPermission.java
index 6d97fbe..6f3bf4a 100644
--- a/ojluni/src/main/java/java/security/UnresolvedPermission.java
+++ b/ojluni/src/main/java/java/security/UnresolvedPermission.java
@@ -34,6 +34,8 @@
import java.lang.reflect.*;
import java.security.cert.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/acl/Permission.java b/ojluni/src/main/java/java/security/acl/Permission.java
index cd84a48..72412de 100644
--- a/ojluni/src/main/java/java/security/acl/Permission.java
+++ b/ojluni/src/main/java/java/security/acl/Permission.java
@@ -25,6 +25,8 @@
package java.security.acl;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/java/security/interfaces/DSAParams.java b/ojluni/src/main/java/java/security/interfaces/DSAParams.java
index b672ad5..8c46ed5 100644
--- a/ojluni/src/main/java/java/security/interfaces/DSAParams.java
+++ b/ojluni/src/main/java/java/security/interfaces/DSAParams.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
diff --git a/ojluni/src/main/java/java/security/spec/ECParameterSpec.java b/ojluni/src/main/java/java/security/spec/ECParameterSpec.java
index 12e252b..65bd027 100644
--- a/ojluni/src/main/java/java/security/spec/ECParameterSpec.java
+++ b/ojluni/src/main/java/java/security/spec/ECParameterSpec.java
@@ -111,7 +111,9 @@
public int getCofactor() {
return h;
}
- // BEGIN Android-changed
+ // BEGIN Android-added: Store the curve name as part of the parameters
+ // Knowing the name of the curve sometimes allows implementations to operate
+ // more efficiently.
private String curveName;
/**
@@ -132,5 +134,5 @@
public String getCurveName() {
return curveName;
}
- // END Android-changed
+ // END Android-added: Store the curve name as part of the parameters
}
diff --git a/ojluni/src/main/java/java/sql/SQLPermission.java b/ojluni/src/main/java/java/sql/SQLPermission.java
index 050f763..505202c 100644
--- a/ojluni/src/main/java/java/sql/SQLPermission.java
+++ b/ojluni/src/main/java/java/sql/SQLPermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/text/SimpleDateFormat.java b/ojluni/src/main/java/java/text/SimpleDateFormat.java
index 700d5ca..6ae9057 100644
--- a/ojluni/src/main/java/java/text/SimpleDateFormat.java
+++ b/ojluni/src/main/java/java/text/SimpleDateFormat.java
@@ -1212,18 +1212,18 @@
break;
case PATTERN_MONTH: // 'M'
- {
- current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
- false /* standalone */);
+ if (useDateFormatSymbols) {
+ current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
+ false /* standalone */);
+ }
break;
- }
case PATTERN_MONTH_STANDALONE: // 'L'
- {
- current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
- true /* standalone */);
+ if (useDateFormatSymbols) {
+ current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
+ true /* standalone */);
+ }
break;
- }
case PATTERN_HOUR_OF_DAY1: // 'k' 1-based. eg, 23:59 + 1 hour =>> 24:59
if (current == null) {
@@ -1237,16 +1237,16 @@
break;
case PATTERN_DAY_OF_WEEK: // 'E'
- {
- current = formatWeekday(count, value, useDateFormatSymbols, false /* standalone */);
+ if (current == null) {
+ current = formatWeekday(count, value, useDateFormatSymbols, false /* standalone */);
+ }
break;
- }
case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
- {
- current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */);
+ if (current == null) {
+ current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */);
+ }
break;
- }
case PATTERN_AM_PM: // 'a'
if (useDateFormatSymbols) {
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/time/chrono/JapaneseDate.java b/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
index 45e6602..143c4a4 100644
--- a/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
+++ b/ojluni/src/main/java/java/time/chrono/JapaneseDate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -432,7 +432,11 @@
field == ALIGNED_WEEK_OF_MONTH || field == ALIGNED_WEEK_OF_YEAR) {
return false;
}
- return ChronoLocalDate.super.isSupported(field);
+ // Android-changed: Apply upstream OpenJDK 9 compilation fix.
+ // Applied OpenJDK 9 change from http://hg.openjdk.java.net/jdk9/dev/jdk/rev/2b7b09c81bf1
+ // On OpenJDK 8, either version is supported and has the same behavior.
+ // return ChronoLocalDate.super.isSupported(field);
+ return super.isSupported(field);
}
@Override
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/Calendar.java b/ojluni/src/main/java/java/util/Calendar.java
index 2009123..b846211 100644
--- a/ojluni/src/main/java/java/util/Calendar.java
+++ b/ojluni/src/main/java/java/util/Calendar.java
@@ -1773,11 +1773,11 @@
public void setTimeInMillis(long millis) {
// If we don't need to recalculate the calendar field values,
// do nothing.
-// BEGIN Android-changed: Removed ZoneInfo support
+// BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet
// && (zone instanceof ZoneInfo) && !((ZoneInfo)zone).isDirty()) {
if (time == millis && isTimeSet && areFieldsSet && areAllFieldsSet) {
-// END Android-changed: Removed ZoneInfo support
+// END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
return;
}
@@ -3508,7 +3508,7 @@
catch (IllegalArgumentException e) {}
}
- // Android-changed: Removed ZoneInfo support/workaround.
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// Write out the 1.1 FCS object.
stream.defaultWriteObject();
}
@@ -3560,7 +3560,7 @@
serialVersionOnStream = currentSerialVersion;
- // Android-changed: removed ZoneInfo support.
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// If the deserialized object has a SimpleTimeZone, try to
// replace it with a ZoneInfo equivalent (as of 1.4) in order
diff --git a/ojluni/src/main/java/java/util/Collections.java b/ojluni/src/main/java/java/util/Collections.java
index 315a7d1..9c379e6 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/EnumMap.java b/ojluni/src/main/java/java/util/EnumMap.java
index a2512a8..207ce62 100644
--- a/ojluni/src/main/java/java/util/EnumMap.java
+++ b/ojluni/src/main/java/java/util/EnumMap.java
@@ -750,9 +750,9 @@
* The result is uncloned, cached, and shared by all callers.
*/
private static <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType) {
- // Android-changed: Use JavaLangAccess directly instead of going through
- // SharedSecrets.
- return JavaLangAccess.getEnumConstantsShared(keyType);
+ // Android-changed: Use getEnumConstantsShared directly instead of going
+ // through SharedSecrets.
+ return keyType.getEnumConstantsShared();
}
private static final long serialVersionUID = 458661240069192865L;
diff --git a/ojluni/src/main/java/java/util/EnumSet.java b/ojluni/src/main/java/java/util/EnumSet.java
index 5d9311a..2443f1e 100644
--- a/ojluni/src/main/java/java/util/EnumSet.java
+++ b/ojluni/src/main/java/java/util/EnumSet.java
@@ -402,9 +402,9 @@
* The result is uncloned, cached, and shared by all callers.
*/
private static <E extends Enum<E>> E[] getUniverse(Class<E> elementType) {
- // Android-changed: Use JavaLangAccess directly instead of going via
- // SharedSecrets.
- return java.lang.JavaLangAccess.getEnumConstantsShared(elementType);
+ // Android-changed: Use getEnumConstantsShared directly instead of going
+ // through SharedSecrets.
+ return elementType.getEnumConstantsShared();
}
/**
diff --git a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
index fef7eed..c569981 100644
--- a/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
+++ b/ojluni/src/main/java/java/util/JapaneseImperialCalendar.java
@@ -1574,10 +1574,14 @@
zoneOffsets = new int[2];
}
if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
- // Android-changed: remove ZoneInfo support.
- zoneOffset = tz.getOffset(time);
- zoneOffsets[0] = tz.getRawOffset();
- zoneOffsets[1] = zoneOffset - zoneOffsets[0];
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (tz instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)tz).getOffsets(time, zoneOffsets);
+ // } else {
+ zoneOffset = tz.getOffset(time);
+ zoneOffsets[0] = tz.getRawOffset();
+ zoneOffsets[1] = zoneOffset - zoneOffsets[0];
+ // }
}
if (tzMask != 0) {
if (isFieldSet(tzMask, ZONE_OFFSET)) {
@@ -1911,8 +1915,12 @@
}
int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
- // Android-changed: remove ZoneInfo support
- zone.getOffsets(millis - zone.getRawOffset(), zoneOffsets);
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zone instanceof ZoneInfo) {
+ // ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets);
+ // } else {
+ zone.getOffsets(millis - zone.getRawOffset(), zoneOffsets);
+ // }
}
if (tzMask != 0) {
if (isFieldSet(tzMask, ZONE_OFFSET)) {
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/PropertyPermission.java b/ojluni/src/main/java/java/util/PropertyPermission.java
index 8b73ce1..ac7b521 100644
--- a/ojluni/src/main/java/java/util/PropertyPermission.java
+++ b/ojluni/src/main/java/java/util/PropertyPermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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 c745291..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,35 +382,44 @@
* @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);
+ }
+ 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;
+ }
}
- // 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;
- }
-
- // If we get here, it's because icu4c has nothing for us. Most commonly, this is in the
- // case of short names. For Pacific/Fiji, for example, icu4c has nothing better to offer
- // than "GMT+12:00". Why do we re-do this work ourselves? Because we have up-to-date
- // time zone transition data, which icu4c _doesn't_ use --- it uses its own baked-in copy,
- // which only gets updated when we update icu4c. http://b/7955614 and http://b/8026776.
-
- // TODO: should we generate these once, in TimeZoneNames.getDisplayName? Revisit when we
- // upgrade to icu4c 50 and rewrite the underlying native code. See also the
- // "element[j] != null" check in SimpleDateFormat.parseTimeZone, and the extra work in
- // DateFormatSymbols.getZoneStrings.
+ // We get here if this is a custom timezone or ICU doesn't have name data for the specific
+ // style and locale.
int offsetMillis = getRawOffset();
if (daylightTime) {
offsetMillis += getDSTSavings();
}
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.
*
@@ -456,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/java/util/logging/LoggingPermission.java b/ojluni/src/main/java/java/util/logging/LoggingPermission.java
index 23c5432..5cea7a5 100644
--- a/ojluni/src/main/java/java/util/logging/LoggingPermission.java
+++ b/ojluni/src/main/java/java/util/logging/LoggingPermission.java
@@ -26,6 +26,8 @@
package java.util.logging;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/Cipher.java b/ojluni/src/main/java/javax/crypto/Cipher.java
index c2a2183..e3c266f 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,11 @@
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 debug =
+ Debug.getInstance("jca", "Cipher");
+
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -835,7 +836,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 +977,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 +1118,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 +1305,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 +2176,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 +2209,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/CryptoAllPermission.java b/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
index 24268b8..8a973fc 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoAllPermission.java
@@ -25,6 +25,8 @@
package javax.crypto;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPermission.java b/ojluni/src/main/java/javax/crypto/CryptoPermission.java
index ec09287..56973b6 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPermission.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPermission.java
@@ -28,6 +28,8 @@
import java.security.*;
import java.security.spec.AlgorithmParameterSpec;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPermissions.java b/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
index 0e62b18..eef08b7 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPermissions.java
@@ -31,6 +31,8 @@
import java.io.InputStream;
import java.io.IOException;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java b/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
index a5a3818..10bdc55 100644
--- a/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
+++ b/ojluni/src/main/java/javax/crypto/CryptoPolicyParser.java
@@ -29,6 +29,8 @@
import java.security.GeneralSecurityException;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/JceSecurity.java b/ojluni/src/main/java/javax/crypto/JceSecurity.java
index 073d827..4572627 100644
--- a/ojluni/src/main/java/javax/crypto/JceSecurity.java
+++ b/ojluni/src/main/java/javax/crypto/JceSecurity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, 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
@@ -64,8 +64,14 @@
private final static Map<Provider, Object> verifyingProviders =
new IdentityHashMap<>();
- // Set the default value. May be changed in the static initializer.
- private static boolean isRestricted = true;
+ // Android-removed: JCE crypto strength restrictions are never in place on Android.
+ // private static final boolean isRestricted = true;
+
+ // Android-removed: This debugging mechanism is not used in Android.
+ /*
+ private static final Debug debug =
+ Debug.getInstance("jca", "Cipher");
+ */
/*
* Don't let anyone instantiate this.
@@ -73,7 +79,7 @@
private JceSecurity() {
}
- // BEGIN Android-changed
+ // BEGIN Android-removed: JCE crypto strength restrictions are never in place on Android.
/*
static {
try {
@@ -93,7 +99,7 @@
}
}
*/
- // END Android-changed
+ // END Android-removed: JCE crypto strength restrictions are never in place on Android.
static Instance getInstance(String type, Class<?> clazz, String algorithm,
String provider) throws NoSuchAlgorithmException,
@@ -201,10 +207,10 @@
// return whether this provider is properly signed and can be used by JCE
static boolean canUseProvider(Provider p) {
- // BEGIN Android-changed
+ // BEGIN Android-changed: All providers are available.
// return getVerificationResult(p) == null;
return true;
- // END Android-changed
+ // END Android-changed: All providers are available.
}
// dummy object to represent null
@@ -212,7 +218,7 @@
static {
try {
- NULL_URL = new URL("http://null.sun.com/");
+ NULL_URL = new URL("http://null.oracle.com/");
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -247,14 +253,71 @@
}
}
+ // BEGIN Android-removed: JCE crypto strength restrictions are never in place on Android.
+ /*
+ * This is called from within an doPrivileged block.
+ *
+ * Following logic is used to decide what policy files are selected.
+ *
+ * If the new Security property (crypto.policy) is set in the
+ * java.security file, or has been set dynamically using the
+ * Security.setProperty() call before the JCE framework has
+ * been initialized, that setting will be used.
+ * Remember - this property is not defined by default. A conscious
+ * user edit or an application call is required.
+ *
+ * Otherwise, if user has policy jar files installed in the legacy
+ * jre/lib/security/ directory, the JDK will honor whatever
+ * setting is set by those policy files. (legacy/current behavior)
+ *
+ * If none of the above 2 conditions are met, the JDK will default
+ * to using the limited crypto policy files found in the
+ * jre/lib/security/policy/limited/ directory
+ *
private static void setupJurisdictionPolicies() throws Exception {
- String javaHomeDir = System.getProperty("java.home");
- String sep = File.separator;
- String pathToPolicyJar = javaHomeDir + sep + "lib" + sep +
- "security" + sep;
+ // Sanity check the crypto.policy Security property. Single
+ // directory entry, no pseudo-directories (".", "..", leading/trailing
+ // path separators). normalize()/getParent() will help later.
+ String javaHomeProperty = System.getProperty("java.home");
+ String cryptoPolicyProperty = Security.getProperty("crypto.policy");
+ Path cpPath = (cryptoPolicyProperty == null) ? null :
+ Paths.get(cryptoPolicyProperty);
- File exportJar = new File(pathToPolicyJar, "US_export_policy.jar");
- File importJar = new File(pathToPolicyJar, "local_policy.jar");
+ if ((cpPath != null) && ((cpPath.getNameCount() != 1) ||
+ (cpPath.compareTo(cpPath.getFileName())) != 0)) {
+ throw new SecurityException(
+ "Invalid policy directory name format: " +
+ cryptoPolicyProperty);
+ }
+
+ if (cpPath == null) {
+ // Security property is not set, use default path
+ cpPath = Paths.get(javaHomeProperty, "lib", "security");
+ } else {
+ // populate with java.home
+ cpPath = Paths.get(javaHomeProperty, "lib", "security",
+ "policy", cryptoPolicyProperty);
+ }
+
+ if (debug != null) {
+ debug.println("crypto policy directory: " + cpPath);
+ }
+
+ File exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
+ File importJar = new File(cpPath.toFile(),"local_policy.jar");
+
+ if (cryptoPolicyProperty == null && (!exportJar.exists() ||
+ !importJar.exists())) {
+ // Compatibility set up. If crypto.policy is not defined.
+ // check to see if legacy jars exist in lib directory. If
+ // they don't exist, we default to limited policy mode.
+ cpPath = Paths.get(
+ javaHomeProperty, "lib", "security", "policy", "limited");
+ // point to the new jar files in limited directory
+ exportJar = new File(cpPath.toFile(),"US_export_policy.jar");
+ importJar = new File(cpPath.toFile(),"local_policy.jar");
+ }
+
URL jceCipherURL = ClassLoader.getSystemResource
("javax/crypto/Cipher.class");
@@ -287,6 +350,8 @@
exemptPolicy = exemptExport.getMinimum(exemptImport);
}
}
+ */
+ // END Android-removed: JCE crypto strength restrictions are never in place on Android.
/**
* Load the policies from the specified file. Also checks that the
@@ -337,7 +402,8 @@
return exemptPolicy;
}
- static boolean isRestricted() {
- return isRestricted;
- }
+ // Android-removed: JCE crypto strength restrictions are never in place on Android.
+ // static boolean isRestricted() {
+ // return isRestricted;
+ // }
}
diff --git a/ojluni/src/main/java/javax/crypto/JceSecurityManager.java b/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
index 38d9f19..aafaa58 100644
--- a/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
+++ b/ojluni/src/main/java/javax/crypto/JceSecurityManager.java
@@ -25,6 +25,8 @@
package javax.crypto;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/crypto/KeyAgreement.java b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
index 8a0b1c1..ffa18b1 100644
--- a/ojluni/src/main/java/javax/crypto/KeyAgreement.java
+++ b/ojluni/src/main/java/javax/crypto/KeyAgreement.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -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,11 @@
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 debug =
+ Debug.getInstance("jca", "KeyAgreement");
+
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -107,6 +108,23 @@
// The name of the key agreement algorithm.
private final String algorithm;
+ // BEGIN Android-removed: Redo the provider selection logic to allow reselecting provider.
+ // When only the algorithm is specified, we want to allow the KeyAgreement provider for that
+ // algorithm to change if multiple providers exist and they support different subsets of
+ // keys. To that end, we don't hold an iterator and exhaust it when we need to choose
+ // a provider like the upstream implementation, we reestablish the list of providers
+ // each time.
+ /*
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator<Service> serviceIterator;
+ */
+ // END Android-removed: Redo the provider selection logic to allow reselecting provider.
+
private final Object lock;
/**
@@ -124,6 +142,7 @@
lock = null;
}
+ // Android-changed: Remove Service and Iterator from constructor args.
private KeyAgreement(String algorithm) {
this.algorithm = algorithm;
lock = new Object();
@@ -184,6 +203,8 @@
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
+ // Android-changed: Remove Service and Iterator from constructor args.
+ // return new KeyAgreement(s, t, algorithm);
return new KeyAgreement(algorithm);
}
throw new NoSuchAlgorithmException
@@ -293,7 +314,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) {
@@ -308,6 +330,7 @@
}
*/
Exception lastException = null;
+ // Android-changed: Provider selection; loop over a new list each time.
for (Service s : GetInstance.getServices("KeyAgreement", algorithm)) {
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
@@ -319,7 +342,12 @@
}
spi = (KeyAgreementSpi)obj;
provider = s.getProvider();
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
// not needed any more
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (Exception e) {
lastException = e;
@@ -351,11 +379,14 @@
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (spi != null) {
if (spi != null && key == null) {
implInit(spi, initType, key, params, random);
return;
}
Exception lastException = null;
+ // Android-changed: Provider selection; loop over a new list each time.
for (Service s : GetInstance.getServices("KeyAgreement", algorithm)) {
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
@@ -369,6 +400,11 @@
implInit(spi, initType, key, params, random);
provider = s.getProvider();
this.spi = spi;
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
@@ -452,6 +488,8 @@
*/
public final void init(Key key, SecureRandom random)
throws InvalidKeyException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (spi != null) {
if (spi != null && (key == null || lock == null)) {
spi.engineInit(key, random);
} else {
@@ -463,7 +501,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 +565,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..c3d99fb 100644
--- a/ojluni/src/main/java/javax/crypto/Mac.java
+++ b/ojluni/src/main/java/javax/crypto/Mac.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -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,11 @@
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 debug =
+ Debug.getInstance("jca", "Mac");
+
private static final Debug pdebug =
Debug.getInstance("provider", "Provider");
private static final boolean skipDebug =
@@ -175,6 +176,23 @@
// Has this object been initialized?
private boolean initialized = false;
+ // BEGIN Android-removed: Redo the provider selection logic to allow reselecting provider.
+ // When only the algorithm is specified, we want to allow the Mac provider for that
+ // algorithm to change if multiple providers exist and they support different subsets of
+ // keys. To that end, we don't hold an iterator and exhaust it when we need to choose
+ // a provider like the upstream implementation, we reestablish the list of providers
+ // each time.
+ /*
+ // next service to try in provider selection
+ // null once provider is selected
+ private Service firstService;
+
+ // remaining services to try in provider selection
+ // null once provider is selected
+ private Iterator<Service> serviceIterator;
+ */
+ // END Android-removed: Redo the provider selection logic to allow reselecting provider.
+
private final Object lock;
/**
@@ -191,6 +209,7 @@
lock = null;
}
+ // Android-changed: Remove Service and Iterator from constructor args.
private Mac(String algorithm) {
this.algorithm = algorithm;
lock = new Object();
@@ -246,6 +265,8 @@
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
}
+ // Android-changed: Remove Service and Iterator from constructor args.
+ // return new Mac(s, t, algorithm);
return new Mac(algorithm);
}
throw new NoSuchAlgorithmException
@@ -337,6 +358,8 @@
* is not the first method called.
*/
void chooseFirstProvider() {
+ // Android-changed: Check if lock is null rather than removed serviceIterator field.
+ // if ((spi != null) || (serviceIterator == null)) {
if (spi != null || lock == null) {
return;
}
@@ -344,7 +367,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) {
@@ -359,6 +383,7 @@
}
*/
Exception lastException = null;
+ // Android-changed: Provider selection; loop over a new list each time.
for (Service s : GetInstance.getServices("Mac", algorithm)) {
if (JceSecurity.canUseProvider(s.getProvider()) == false) {
continue;
@@ -370,6 +395,12 @@
}
spi = (MacSpi)obj;
provider = s.getProvider();
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ // not needed any more
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (NoSuchAlgorithmException e) {
lastException = e;
@@ -387,11 +418,14 @@
private void chooseProvider(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
synchronized (lock) {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (spi != null) {
if (spi != null && (key == null || lock == null)) {
spi.engineInit(key, params);
return;
}
Exception lastException = null;
+ // Android-changed: Provider selection; loop over a new list each time.
for (Service s : GetInstance.getServices("Mac", algorithm)) {
// if provider says it does not support this key, ignore it
if (s.supportsParameter(key) == false) {
@@ -405,6 +439,11 @@
spi.engineInit(key, params);
provider = s.getProvider();
this.spi = spi;
+ // Android-removed: Provider selection; loop over a new list each time.
+ /*
+ firstService = null;
+ serviceIterator = null;
+ */
return;
} catch (Exception e) {
// NoSuchAlgorithmException from newInstance()
@@ -462,6 +501,8 @@
*/
public final void init(Key key) throws InvalidKeyException {
try {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (spi != null) {
if (spi != null && (key == null || lock == null)) {
spi.engineInit(key, null);
} else {
@@ -472,7 +513,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());
@@ -494,6 +536,8 @@
*/
public final void init(Key key, AlgorithmParameterSpec params)
throws InvalidKeyException, InvalidAlgorithmParameterException {
+ // Android-changed: Use the currently-selected provider only if no key was provided.
+ // if (spi != null) {
if (spi != null && (key == null || lock == null)) {
spi.engineInit(key, params);
} else {
@@ -501,7 +545,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());
@@ -727,6 +772,7 @@
return that;
}
+ // BEGIN Android-added: Allow access to the current SPI for testing purposes.
/**
* Returns the {@code MacSpi} backing this {@code Mac} or {@code null} if no {@code MacSpi} is
* backing this {@code Mac}.
@@ -736,4 +782,5 @@
public MacSpi getCurrentSpi() {
return spi;
}
+ // END Android-added: Allow access to the current SPI for testing purposes.
}
diff --git a/ojluni/src/main/java/javax/net/SocketFactory.java b/ojluni/src/main/java/javax/net/SocketFactory.java
index 2bcfac3..3c89371 100644
--- a/ojluni/src/main/java/javax/net/SocketFactory.java
+++ b/ojluni/src/main/java/javax/net/SocketFactory.java
@@ -104,6 +104,7 @@
return theFactory;
}
+ // Android-added: Added method for testing default socket factory.
/** @hide Visible for testing only */
public static void setDefault(SocketFactory factory) {
synchronized (SocketFactory.class) {
diff --git a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
index 9660643..ec4254a 100644
--- a/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
+++ b/ojluni/src/main/java/javax/net/ssl/HttpsURLConnection.java
@@ -178,6 +178,10 @@
}
}
+ // BEGIN Android-changed: Use lazily-created OkHttp hostname verifier
+ // The RI default hostname verifier is a static member of the class, which means
+ // it's created when the class is initialized. As well, its default verifier
+ // just fails all verification attempts, whereas we use OkHttp's verifier.
/*
* Holds the default instance so class preloading doesn't create an instance of
* it.
@@ -207,6 +211,7 @@
* The <code>hostnameVerifier</code> for this object.
*/
protected HostnameVerifier hostnameVerifier;
+ // END Android-changed: Use lazily-created OkHttp hostname verifier
/**
* Sets the default <code>HostnameVerifier</code> inherited by a
@@ -279,6 +284,7 @@
* @see #setDefaultHostnameVerifier(HostnameVerifier)
*/
public HostnameVerifier getHostnameVerifier() {
+ // Android-added: Use the default verifier if none is set
if (hostnameVerifier == null) {
hostnameVerifier = NoPreloadHolder.defaultHostnameVerifier;
}
diff --git a/ojluni/src/main/java/javax/net/ssl/SNIServerName.java b/ojluni/src/main/java/javax/net/ssl/SNIServerName.java
index c5bb253..1ef9d05 100644
--- a/ojluni/src/main/java/javax/net/ssl/SNIServerName.java
+++ b/ojluni/src/main/java/javax/net/ssl/SNIServerName.java
@@ -210,3 +210,4 @@
return sb.toString();
}
}
+
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLContext.java b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
index 71cfc23..4105282 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLContext.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLContext.java
@@ -178,7 +178,7 @@
* @return the new <code>SSLContext</code> object.
*
* @exception NoSuchAlgorithmException if no Provider supports a
- * TrustManagerFactorySpi implementation for the
+ * SSLContextSpi implementation for the
* specified protocol.
* @exception NullPointerException if protocol is null.
*
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
index 35481e4..a513c49 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLEngine.java
@@ -329,6 +329,7 @@
* is saved. All future delegated tasks will be processed using this
* context: that is, all access control decisions will be made using the
* context captured at engine creation.
+ *
* <HR>
*
* <B>Concurrency Notes</B>:
@@ -1183,7 +1184,7 @@
* If this <code>SSLEngine</code> has not yet started its initial
* handshake, this method will automatically start the handshake.
* <P>
- * This method will attempt to produce one SSL/TLS packet, and will
+ * This method will attempt to produce SSL/TLS records, and will
* consume as much source data as possible, but will never consume
* more than the sum of the bytes remaining in each buffer. Each
* <code>ByteBuffer</code>'s position is updated to reflect the
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLPermission.java b/ojluni/src/main/java/javax/net/ssl/SSLPermission.java
index 0f6b5db..a23e1ce 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLPermission.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLPermission.java
@@ -27,6 +27,8 @@
import java.security.*;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java b/ojluni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
index a480c60..2db63bb 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLServerSocketFactory.java
@@ -45,8 +45,16 @@
*/
public abstract class SSLServerSocketFactory extends ServerSocketFactory
{
+ // Android-changed: Renamed field.
+ // Some apps rely on changing this field via reflection, so we can't change the name
+ // without introducing app compatibility problems. See http://b/62248930.
private static SSLServerSocketFactory defaultServerSocketFactory;
+ // Android-changed: Check Security.getVersion() on each update.
+ // If the set of providers or other such things changes, it may change the default
+ // factory, so we track the version returned from Security.getVersion() instead of
+ // only having a flag that says if we've ever initialized the default.
+ // private static boolean propertyChecked;
private static int lastVersion = -1;
private static void log(String msg) {
@@ -77,10 +85,7 @@
* @see SSLContext#getDefault
*/
public static synchronized ServerSocketFactory getDefault() {
- // Android-changed: Use security version instead of propertyChecked.
- //
- // We use the same lookup logic in SSLSocketFactory.getDefault(). Any changes
- // made here must be mirrored in that class.
+ // Android-changed: Check Security.getVersion() on each update.
if (defaultServerSocketFactory != null && lastVersion == Security.getVersion()) {
return defaultServerSocketFactory;
}
@@ -90,8 +95,9 @@
defaultServerSocketFactory = null;
String clsName = SSLSocketFactory.getSecurityProperty
- ("ssl.ServerSocketFactory.provider");
+ ("ssl.ServerSocketFactory.provider");
if (clsName != null) {
+ // Android-changed: Check if we already have an instance of the default factory class.
// The instance for the default socket factory is checked for updates quite
// often (for instance, every time a security provider is added). Which leads
// to unnecessary overload and excessive error messages in case of class-loading
@@ -101,10 +107,9 @@
defaultServerSocketFactory = previousDefaultServerSocketFactory;
return defaultServerSocketFactory;
}
- Class cls = null;
log("setting up default SSLServerSocketFactory");
try {
- log("setting up default SSLServerSocketFactory");
+ Class<?> cls = null;
try {
cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
@@ -115,37 +120,33 @@
}
if (cl != null) {
+ // Android-changed: Use Class.forName() so the class gets initialized.
cls = Class.forName(clsName, true, cl);
}
}
log("class " + clsName + " is loaded");
- SSLServerSocketFactory fac = (SSLServerSocketFactory) cls.newInstance();
+ SSLServerSocketFactory fac = (SSLServerSocketFactory)cls.newInstance();
log("instantiated an instance of class " + clsName);
defaultServerSocketFactory = fac;
- if (defaultServerSocketFactory != null) {
- return defaultServerSocketFactory;
- }
+ return fac;
} catch (Exception e) {
log("SSLServerSocketFactory instantiation failed: " + e);
- // Android-changed: Fallback to the default SSLContext if an exception
- // is thrown during the initialization of ssl.ServerSocketFactory.provider.
+ // Android-changed: Fallback to the default SSLContext on exception.
}
}
try {
+ // Android-changed: Allow for {@code null} SSLContext.getDefault.
SSLContext context = SSLContext.getDefault();
if (context != null) {
defaultServerSocketFactory = context.getServerSocketFactory();
+ } else {
+ defaultServerSocketFactory = new DefaultSSLServerSocketFactory(new IllegalStateException("No factory found."));
}
+ return defaultServerSocketFactory;
} catch (NoSuchAlgorithmException e) {
+ return new DefaultSSLServerSocketFactory(e);
}
-
- if (defaultServerSocketFactory == null) {
- defaultServerSocketFactory = new DefaultSSLServerSocketFactory(
- new IllegalStateException("No ServerSocketFactory implementation found"));
- }
-
- return defaultServerSocketFactory;
}
/**
diff --git a/ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java b/ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java
index f1d7057..93b5dc7 100644
--- a/ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java
+++ b/ojluni/src/main/java/javax/net/ssl/SSLSocketFactory.java
@@ -30,6 +30,7 @@
import java.net.*;
import javax.net.SocketFactory;
import java.io.IOException;
+import java.io.InputStream;
import java.security.*;
import java.util.Locale;
@@ -44,8 +45,16 @@
*/
public abstract class SSLSocketFactory extends SocketFactory
{
+ // Android-changed: Renamed field.
+ // Some apps rely on changing this field via reflection, so we can't change the name
+ // without introducing app compatibility problems. See http://b/62248930.
private static SSLSocketFactory defaultSocketFactory;
+ // Android-changed: Check Security.getVersion() on each update.
+ // If the set of providers or other such things changes, it may change the default
+ // factory, so we track the version returned from Security.getVersion() instead of
+ // only having a flag that says if we've ever initialized the default.
+ // private static boolean propertyChecked;
private static int lastVersion = -1;
static final boolean DEBUG;
@@ -86,7 +95,7 @@
* @see SSLContext#getDefault
*/
public static synchronized SocketFactory getDefault() {
- // Android-changed: Use security version instead of propertyChecked.
+ // Android-changed: Check Security.getVersion() on each update.
if (defaultSocketFactory != null && lastVersion == Security.getVersion()) {
return defaultSocketFactory;
}
@@ -98,6 +107,7 @@
String clsName = getSecurityProperty("ssl.SocketFactory.provider");
if (clsName != null) {
+ // Android-changed: Check if we already have an instance of the default factory class.
// The instance for the default socket factory is checked for updates quite
// often (for instance, every time a security provider is added). Which leads
// to unnecessary overload and excessive error messages in case of class-loading
@@ -109,49 +119,49 @@
}
log("setting up default SSLSocketFactory");
try {
- Class cls = null;
+ Class<?> cls = null;
try {
cls = Class.forName(clsName);
} catch (ClassNotFoundException e) {
- // Android-changed; Try the contextClassLoader first.
+ // Android-changed: Try the contextClassLoader first.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
}
if (cl != null) {
+ // Android-changed: Use Class.forName() so the class gets initialized.
cls = Class.forName(clsName, true, cl);
}
}
log("class " + clsName + " is loaded");
- defaultSocketFactory = (SSLSocketFactory)cls.newInstance();
+ SSLSocketFactory fac = (SSLSocketFactory)cls.newInstance();
log("instantiated an instance of class " + clsName);
- if (defaultSocketFactory != null) {
- return defaultSocketFactory;
- }
+ defaultSocketFactory = fac;
+ return fac;
} catch (Exception e) {
log("SSLSocketFactory instantiation failed: " + e.toString());
+ // Android-changed: Fallback to the default SSLContext on exception.
}
}
- // Android-changed: Allow for {@code null} SSLContext.getDefault.
try {
+ // Android-changed: Allow for {@code null} SSLContext.getDefault.
SSLContext context = SSLContext.getDefault();
if (context != null) {
defaultSocketFactory = context.getSocketFactory();
+ } else {
+ defaultSocketFactory = new DefaultSSLSocketFactory(new IllegalStateException("No factory found."));
}
+ return defaultSocketFactory;
} catch (NoSuchAlgorithmException e) {
+ return new DefaultSSLSocketFactory(e);
}
-
- if (defaultSocketFactory == null) {
- defaultSocketFactory = new DefaultSSLSocketFactory(new IllegalStateException("No factory found."));
- }
-
- return defaultSocketFactory;
}
static String getSecurityProperty(final String name) {
return AccessController.doPrivileged(new PrivilegedAction<String>() {
+ @Override
public String run() {
String s = java.security.Security.getProperty(name);
if (s != null) {
@@ -207,6 +217,56 @@
*/
public abstract Socket createSocket(Socket s, String host,
int port, boolean autoClose) throws IOException;
+
+ /**
+ * Creates a server mode {@link Socket} layered over an
+ * existing connected socket, and is able to read data which has
+ * already been consumed/removed from the {@link Socket}'s
+ * underlying {@link InputStream}.
+ * <p>
+ * This method can be used by a server application that needs to
+ * observe the inbound data but still create valid SSL/TLS
+ * connections: for example, inspection of Server Name Indication
+ * (SNI) extensions (See section 3 of <A
+ * HREF="http://www.ietf.org/rfc/rfc6066.txt">TLS Extensions
+ * (RFC6066)</A>). Data that has been already removed from the
+ * underlying {@link InputStream} should be loaded into the
+ * {@code consumed} stream before this method is called, perhaps
+ * using a {@link java.io.ByteArrayInputStream}. When this
+ * {@link Socket} begins handshaking, it will read all of the data in
+ * {@code consumed} until it reaches {@code EOF}, then all further
+ * data is read from the underlying {@link InputStream} as
+ * usual.
+ * <p>
+ * The returned socket is configured using the socket options
+ * established for this factory, and is set to use server mode when
+ * handshaking (see {@link SSLSocket#setUseClientMode(boolean)}).
+ *
+ * @param s
+ * the existing socket
+ * @param consumed
+ * the consumed inbound network data that has already been
+ * removed from the existing {@link Socket}
+ * {@link InputStream}. This parameter may be
+ * {@code null} if no data has been removed.
+ * @param autoClose close the underlying socket when this socket is closed.
+ *
+ * @return the {@link Socket} compliant with the socket options
+ * established for this factory
+ *
+ * @throws IOException if an I/O error occurs when creating the socket
+ * @throws UnsupportedOperationException if the underlying provider
+ * does not implement the operation
+ * @throws NullPointerException if {@code s} is {@code null}
+ *
+ * @since 1.8
+ *
+ * @hide
+ */
+ public Socket createSocket(Socket s, InputStream consumed,
+ boolean autoClose) throws IOException {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/ojluni/src/main/java/javax/security/auth/AuthPermission.java b/ojluni/src/main/java/javax/security/auth/AuthPermission.java
index 651e9a3..71c3aaf 100644
--- a/ojluni/src/main/java/javax/security/auth/AuthPermission.java
+++ b/ojluni/src/main/java/javax/security/auth/AuthPermission.java
@@ -25,6 +25,8 @@
package javax.security.auth;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java b/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
index ca52a1b2..9733932 100644
--- a/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
+++ b/ojluni/src/main/java/javax/security/auth/PrivateCredentialPermission.java
@@ -29,6 +29,8 @@
import java.security.Permission;
import java.security.Principal;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java b/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
index 8e07d4b..868ed5f 100644
--- a/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
+++ b/ojluni/src/main/java/javax/security/auth/SubjectDomainCombiner.java
@@ -27,6 +27,8 @@
import java.security.ProtectionDomain;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
diff --git a/ojluni/src/main/java/jdk/net/NetworkPermission.java b/ojluni/src/main/java/jdk/net/NetworkPermission.java
index 420c74f..96d7a8e 100644
--- a/ojluni/src/main/java/jdk/net/NetworkPermission.java
+++ b/ojluni/src/main/java/jdk/net/NetworkPermission.java
@@ -27,6 +27,8 @@
import java.security.BasicPermission;
+// Android-changed: Stubbed the implementation. Android doesn't support SecurityManager.
+// See comments in java.lang.SecurityManager for details.
/**
* Legacy security code; do not use.
*/
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/BASE64Decoder.java b/ojluni/src/main/java/sun/misc/BASE64Decoder.java
index 63f1228..e65a1d2 100644
--- a/ojluni/src/main/java/sun/misc/BASE64Decoder.java
+++ b/ojluni/src/main/java/sun/misc/BASE64Decoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2000, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -102,6 +102,7 @@
/**
* Decode one BASE64 atom into 1, 2, or 3 bytes of data.
*/
+ @SuppressWarnings("fallthrough")
protected void decodeAtom(PushbackInputStream inStream, OutputStream outStream, int rem)
throws java.io.IOException
{
diff --git a/ojluni/src/main/java/sun/misc/CEFormatException.java b/ojluni/src/main/java/sun/misc/CEFormatException.java
index 974a55c..6d53fa2 100644
--- a/ojluni/src/main/java/sun/misc/CEFormatException.java
+++ b/ojluni/src/main/java/sun/misc/CEFormatException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -28,7 +28,9 @@
import java.io.IOException;
public class CEFormatException extends IOException {
- public CEFormatException(String s) {
- super(s);
- }
+ static final long serialVersionUID = -7139121221067081482L;
+ public CEFormatException(String s) {
+ super(s);
+ }
}
+
diff --git a/ojluni/src/main/java/sun/misc/CEStreamExhausted.java b/ojluni/src/main/java/sun/misc/CEStreamExhausted.java
index 28e0ffe..fb2054e 100644
--- a/ojluni/src/main/java/sun/misc/CEStreamExhausted.java
+++ b/ojluni/src/main/java/sun/misc/CEStreamExhausted.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -27,4 +27,7 @@
import java.io.IOException;
/** This exception is thrown when EOF is reached */
-public class CEStreamExhausted extends IOException { };
+public class CEStreamExhausted extends IOException {
+ static final long serialVersionUID = -5889118049525891904L;
+}
+
diff --git a/ojluni/src/main/java/sun/misc/CharacterDecoder.java b/ojluni/src/main/java/sun/misc/CharacterDecoder.java
index 76b04ea..728e7602 100644
--- a/ojluni/src/main/java/sun/misc/CharacterDecoder.java
+++ b/ojluni/src/main/java/sun/misc/CharacterDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -145,7 +145,7 @@
* Decode the text from the InputStream and write the decoded
* octets to the OutputStream. This method runs until the stream
* is exhausted.
- * @exception CEFormatException An error has occured while decoding
+ * @exception CEFormatException An error has occurred while decoding
* @exception CEStreamExhausted The input stream is unexpectedly out of data
*/
public void decodeBuffer(InputStream aStream, OutputStream bStream) throws IOException {
@@ -181,7 +181,7 @@
/**
* Alternate decode interface that takes a String containing the encoded
* buffer and returns a byte array containing the data.
- * @exception CEFormatException An error has occured while decoding
+ * @exception CEFormatException An error has occurred while decoding
*/
public byte decodeBuffer(String inputString)[] throws IOException {
byte inputBuffer[] = new byte[inputString.length()];
diff --git a/ojluni/src/main/java/sun/misc/Cleaner.java b/ojluni/src/main/java/sun/misc/Cleaner.java
index f23764e..5e92f35 100644
--- a/ojluni/src/main/java/sun/misc/Cleaner.java
+++ b/ojluni/src/main/java/sun/misc/Cleaner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -57,14 +57,14 @@
*/
public class Cleaner
- extends PhantomReference
+ extends PhantomReference<Object>
{
// Dummy reference queue, needed because the PhantomReference constructor
// insists that we pass a queue. Nothing will ever be placed on this queue
// since the reference handler invokes cleaners explicitly.
//
- private static final ReferenceQueue dummyQueue = new ReferenceQueue();
+ private static final ReferenceQueue<Object> dummyQueue = new ReferenceQueue<>();
// Doubly-linked list of live cleaners, which prevents the cleaners
// themselves from being GC'd before their referents
@@ -119,6 +119,7 @@
/**
* Creates a new cleaner.
*
+ * @param ob the referent object to be cleaned
* @param thunk
* The cleanup code to be run when the cleaner is invoked. The
* cleanup code is run directly from the reference-handler thread,
diff --git a/ojluni/src/main/java/sun/misc/CompoundEnumeration.java b/ojluni/src/main/java/sun/misc/CompoundEnumeration.java
index 69de7f8..a89ec5f 100644
--- a/ojluni/src/main/java/sun/misc/CompoundEnumeration.java
+++ b/ojluni/src/main/java/sun/misc/CompoundEnumeration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -33,10 +33,10 @@
* enumerations.
*/
public class CompoundEnumeration<E> implements Enumeration<E> {
- private Enumeration[] enums;
+ private Enumeration<E>[] enums;
private int index = 0;
- public CompoundEnumeration(Enumeration[] enums) {
+ public CompoundEnumeration(Enumeration<E>[] enums) {
this.enums = enums;
}
@@ -58,6 +58,6 @@
if (!next()) {
throw new NoSuchElementException();
}
- return (E)enums[index].nextElement();
+ return enums[index].nextElement();
}
}
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/misc/FpUtils.java b/ojluni/src/main/java/sun/misc/FpUtils.java
index 1050d32..a874c80 100644
--- a/ojluni/src/main/java/sun/misc/FpUtils.java
+++ b/ojluni/src/main/java/sun/misc/FpUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -125,10 +125,6 @@
*/
private FpUtils() {}
- // Constants used in scalb
- static double twoToTheDoubleScaleUp = powerOfTwoD(512);
- static double twoToTheDoubleScaleDown = powerOfTwoD(-512);
-
// Helper Methods
// The following helper methods are used in the implementation of
@@ -137,49 +133,22 @@
/**
* Returns unbiased exponent of a {@code double}.
+ * @deprecated Use Math.getExponent.
*/
+ @Deprecated
public static int getExponent(double d){
- /*
- * Bitwise convert d to long, mask out exponent bits, shift
- * to the right and then subtract out double's bias adjust to
- * get true exponent value.
- */
- return (int)(((Double.doubleToRawLongBits(d) & DoubleConsts.EXP_BIT_MASK) >>
- (DoubleConsts.SIGNIFICAND_WIDTH - 1)) - DoubleConsts.EXP_BIAS);
+ return Math.getExponent(d);
}
/**
* Returns unbiased exponent of a {@code float}.
+ * @deprecated Use Math.getExponent.
*/
+ @Deprecated
public static int getExponent(float f){
- /*
- * Bitwise convert f to integer, mask out exponent bits, shift
- * to the right and then subtract out float's bias adjust to
- * get true exponent value
- */
- return ((Float.floatToRawIntBits(f) & FloatConsts.EXP_BIT_MASK) >>
- (FloatConsts.SIGNIFICAND_WIDTH - 1)) - FloatConsts.EXP_BIAS;
+ return Math.getExponent(f);
}
- /**
- * Returns a floating-point power of two in the normal range.
- */
- static double powerOfTwoD(int n) {
- assert(n >= DoubleConsts.MIN_EXPONENT && n <= DoubleConsts.MAX_EXPONENT);
- return Double.longBitsToDouble((((long)n + (long)DoubleConsts.EXP_BIAS) <<
- (DoubleConsts.SIGNIFICAND_WIDTH-1))
- & DoubleConsts.EXP_BIT_MASK);
- }
-
- /**
- * Returns a floating-point power of two in the normal range.
- */
- static float powerOfTwoF(int n) {
- assert(n >= FloatConsts.MIN_EXPONENT && n <= FloatConsts.MAX_EXPONENT);
- return Float.intBitsToFloat(((n + FloatConsts.EXP_BIAS) <<
- (FloatConsts.SIGNIFICAND_WIDTH-1))
- & FloatConsts.EXP_BIT_MASK);
- }
/**
* Returns the first floating-point argument with the sign of the
@@ -195,13 +164,11 @@
* @return a value with the magnitude of {@code magnitude}
* and the sign of {@code sign}.
* @author Joseph D. Darcy
+ * @deprecated Use Math.copySign.
*/
+ @Deprecated
public static double rawCopySign(double magnitude, double sign) {
- return Double.longBitsToDouble((Double.doubleToRawLongBits(sign) &
- (DoubleConsts.SIGN_BIT_MASK)) |
- (Double.doubleToRawLongBits(magnitude) &
- (DoubleConsts.EXP_BIT_MASK |
- DoubleConsts.SIGNIF_BIT_MASK)));
+ return Math.copySign(magnitude, sign);
}
/**
@@ -218,13 +185,11 @@
* @return a value with the magnitude of {@code magnitude}
* and the sign of {@code sign}.
* @author Joseph D. Darcy
+ * @deprecated Use Math.copySign.
*/
+ @Deprecated
public static float rawCopySign(float magnitude, float sign) {
- return Float.intBitsToFloat((Float.floatToRawIntBits(sign) &
- (FloatConsts.SIGN_BIT_MASK)) |
- (Float.floatToRawIntBits(magnitude) &
- (FloatConsts.EXP_BIT_MASK |
- FloatConsts.SIGNIF_BIT_MASK)));
+ return Math.copySign(magnitude, sign);
}
/* ***************************************************************** */
@@ -237,9 +202,11 @@
* @param d the {@code double} value to be tested
* @return {@code true} if the argument is a finite
* floating-point value, {@code false} otherwise.
+ * @deprecated Use Double.isFinite.
*/
+ @Deprecated
public static boolean isFinite(double d) {
- return Math.abs(d) <= DoubleConsts.MAX_VALUE;
+ return Double.isFinite(d);
}
/**
@@ -250,9 +217,11 @@
* @param f the {@code float} value to be tested
* @return {@code true} if the argument is a finite
* floating-point value, {@code false} otherwise.
+ * @deprecated Use Float.isFinite.
*/
+ @Deprecated
public static boolean isFinite(float f) {
- return Math.abs(f) <= FloatConsts.MAX_VALUE;
+ return Float.isFinite(f);
}
/**
@@ -558,82 +527,11 @@
* @param scale_factor power of 2 used to scale {@code d}
* @return {@code d * }2<sup>{@code scale_factor}</sup>
* @author Joseph D. Darcy
+ * @deprecated Use Math.scalb.
*/
+ @Deprecated
public static double scalb(double d, int scale_factor) {
- /*
- * This method does not need to be declared strictfp to
- * compute the same correct result on all platforms. When
- * scaling up, it does not matter what order the
- * multiply-store operations are done; the result will be
- * finite or overflow regardless of the operation ordering.
- * However, to get the correct result when scaling down, a
- * particular ordering must be used.
- *
- * When scaling down, the multiply-store operations are
- * sequenced so that it is not possible for two consecutive
- * multiply-stores to return subnormal results. If one
- * multiply-store result is subnormal, the next multiply will
- * round it away to zero. This is done by first multiplying
- * by 2 ^ (scale_factor % n) and then multiplying several
- * times by by 2^n as needed where n is the exponent of number
- * that is a covenient power of two. In this way, at most one
- * real rounding error occurs. If the double value set is
- * being used exclusively, the rounding will occur on a
- * multiply. If the double-extended-exponent value set is
- * being used, the products will (perhaps) be exact but the
- * stores to d are guaranteed to round to the double value
- * set.
- *
- * It is _not_ a valid implementation to first multiply d by
- * 2^MIN_EXPONENT and then by 2 ^ (scale_factor %
- * MIN_EXPONENT) since even in a strictfp program double
- * rounding on underflow could occur; e.g. if the scale_factor
- * argument was (MIN_EXPONENT - n) and the exponent of d was a
- * little less than -(MIN_EXPONENT - n), meaning the final
- * result would be subnormal.
- *
- * Since exact reproducibility of this method can be achieved
- * without any undue performance burden, there is no
- * compelling reason to allow double rounding on underflow in
- * scalb.
- */
-
- // magnitude of a power of two so large that scaling a finite
- // nonzero value by it would be guaranteed to over or
- // underflow; due to rounding, scaling down takes takes an
- // additional power of two which is reflected here
- final int MAX_SCALE = DoubleConsts.MAX_EXPONENT + -DoubleConsts.MIN_EXPONENT +
- DoubleConsts.SIGNIFICAND_WIDTH + 1;
- int exp_adjust = 0;
- int scale_increment = 0;
- double exp_delta = Double.NaN;
-
- // Make sure scaling factor is in a reasonable range
-
- if(scale_factor < 0) {
- scale_factor = Math.max(scale_factor, -MAX_SCALE);
- scale_increment = -512;
- exp_delta = twoToTheDoubleScaleDown;
- }
- else {
- scale_factor = Math.min(scale_factor, MAX_SCALE);
- scale_increment = 512;
- exp_delta = twoToTheDoubleScaleUp;
- }
-
- // Calculate (scale_factor % +/-512), 512 = 2^9, using
- // technique from "Hacker's Delight" section 10-2.
- int t = (scale_factor >> 9-1) >>> 32 - 9;
- exp_adjust = ((scale_factor + t) & (512 -1)) - t;
-
- d *= powerOfTwoD(exp_adjust);
- scale_factor -= exp_adjust;
-
- while(scale_factor != 0) {
- d *= exp_delta;
- scale_factor -= scale_increment;
- }
- return d;
+ return Math.scalb(d, scale_factor);
}
/**
@@ -667,28 +565,11 @@
* @param scale_factor power of 2 used to scale {@code f}
* @return {@code f * }2<sup>{@code scale_factor}</sup>
* @author Joseph D. Darcy
+ * @deprecated Use Math.scalb.
*/
- public static float scalb(float f, int scale_factor) {
- // magnitude of a power of two so large that scaling a finite
- // nonzero value by it would be guaranteed to over or
- // underflow; due to rounding, scaling down takes takes an
- // additional power of two which is reflected here
- final int MAX_SCALE = FloatConsts.MAX_EXPONENT + -FloatConsts.MIN_EXPONENT +
- FloatConsts.SIGNIFICAND_WIDTH + 1;
-
- // Make sure scaling factor is in a reasonable range
- scale_factor = Math.max(Math.min(scale_factor, MAX_SCALE), -MAX_SCALE);
-
- /*
- * Since + MAX_SCALE for float fits well within the double
- * exponent range and + float -> double conversion is exact
- * the multiplication below will be exact. Therefore, the
- * rounding that occurs when the double product is cast to
- * float will be the correctly rounded float result. Since
- * all operations other than the final multiply will be exact,
- * it is not necessary to declare this method strictfp.
- */
- return (float)((double)f*powerOfTwoD(scale_factor));
+ @Deprecated
+ public static float scalb(float f, int scale_factor) {
+ return Math.scalb(f, scale_factor);
}
/**
@@ -730,65 +611,11 @@
* @return The floating-point number adjacent to {@code start} in the
* direction of {@code direction}.
* @author Joseph D. Darcy
+ * @deprecated Use Math.nextAfter
*/
+ @Deprecated
public static double nextAfter(double start, double direction) {
- /*
- * The cases:
- *
- * nextAfter(+infinity, 0) == MAX_VALUE
- * nextAfter(+infinity, +infinity) == +infinity
- * nextAfter(-infinity, 0) == -MAX_VALUE
- * nextAfter(-infinity, -infinity) == -infinity
- *
- * are naturally handled without any additional testing
- */
-
- // First check for NaN values
- if (isNaN(start) || isNaN(direction)) {
- // return a NaN derived from the input NaN(s)
- return start + direction;
- } else if (start == direction) {
- return direction;
- } else { // start > direction or start < direction
- // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
- // then bitwise convert start to integer.
- long transducer = Double.doubleToRawLongBits(start + 0.0d);
-
- /*
- * IEEE 754 floating-point numbers are lexicographically
- * ordered if treated as signed- magnitude integers .
- * Since Java's integers are two's complement,
- * incrementing" the two's complement representation of a
- * logically negative floating-point value *decrements*
- * the signed-magnitude representation. Therefore, when
- * the integer representation of a floating-point values
- * is less than zero, the adjustment to the representation
- * is in the opposite direction than would be expected at
- * first .
- */
- if (direction > start) { // Calculate next greater value
- transducer = transducer + (transducer >= 0L ? 1L:-1L);
- } else { // Calculate next lesser value
- assert direction < start;
- if (transducer > 0L)
- --transducer;
- else
- if (transducer < 0L )
- ++transducer;
- /*
- * transducer==0, the result is -MIN_VALUE
- *
- * The transition from zero (implicitly
- * positive) to the smallest negative
- * signed magnitude value must be done
- * explicitly.
- */
- else
- transducer = DoubleConsts.SIGN_BIT_MASK | 1L;
- }
-
- return Double.longBitsToDouble(transducer);
- }
+ return Math.nextAfter(start, direction);
}
/**
@@ -830,65 +657,11 @@
* @return The floating-point number adjacent to {@code start} in the
* direction of {@code direction}.
* @author Joseph D. Darcy
+ * @deprecated Use Math.nextAfter.
*/
- public static float nextAfter(float start, double direction) {
- /*
- * The cases:
- *
- * nextAfter(+infinity, 0) == MAX_VALUE
- * nextAfter(+infinity, +infinity) == +infinity
- * nextAfter(-infinity, 0) == -MAX_VALUE
- * nextAfter(-infinity, -infinity) == -infinity
- *
- * are naturally handled without any additional testing
- */
-
- // First check for NaN values
- if (isNaN(start) || isNaN(direction)) {
- // return a NaN derived from the input NaN(s)
- return start + (float)direction;
- } else if (start == direction) {
- return (float)direction;
- } else { // start > direction or start < direction
- // Add +0.0 to get rid of a -0.0 (+0.0 + -0.0 => +0.0)
- // then bitwise convert start to integer.
- int transducer = Float.floatToRawIntBits(start + 0.0f);
-
- /*
- * IEEE 754 floating-point numbers are lexicographically
- * ordered if treated as signed- magnitude integers .
- * Since Java's integers are two's complement,
- * incrementing" the two's complement representation of a
- * logically negative floating-point value *decrements*
- * the signed-magnitude representation. Therefore, when
- * the integer representation of a floating-point values
- * is less than zero, the adjustment to the representation
- * is in the opposite direction than would be expected at
- * first.
- */
- if (direction > start) {// Calculate next greater value
- transducer = transducer + (transducer >= 0 ? 1:-1);
- } else { // Calculate next lesser value
- assert direction < start;
- if (transducer > 0)
- --transducer;
- else
- if (transducer < 0 )
- ++transducer;
- /*
- * transducer==0, the result is -MIN_VALUE
- *
- * The transition from zero (implicitly
- * positive) to the smallest negative
- * signed magnitude value must be done
- * explicitly.
- */
- else
- transducer = FloatConsts.SIGN_BIT_MASK | 1;
- }
-
- return Float.intBitsToFloat(transducer);
- }
+ @Deprecated
+ public static float nextAfter(float start, double direction) {
+ return Math.nextAfter(start, direction);
}
/**
@@ -915,15 +688,11 @@
* @return The adjacent floating-point value closer to positive
* infinity.
* @author Joseph D. Darcy
+ * @deprecated use Math.nextUp.
*/
+ @Deprecated
public static double nextUp(double d) {
- if( isNaN(d) || d == Double.POSITIVE_INFINITY)
- return d;
- else {
- d += 0.0d;
- return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
- ((d >= 0.0d)?+1L:-1L));
- }
+ return Math.nextUp(d);
}
/**
@@ -950,15 +719,11 @@
* @return The adjacent floating-point value closer to positive
* infinity.
* @author Joseph D. Darcy
+ * @deprecated Use Math.nextUp.
*/
- public static float nextUp(float f) {
- if( isNaN(f) || f == FloatConsts.POSITIVE_INFINITY)
- return f;
- else {
- f += 0.0f;
- return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
- ((f >= 0.0f)?+1:-1));
- }
+ @Deprecated
+ public static float nextUp(float f) {
+ return Math.nextUp(f);
}
/**
@@ -985,17 +750,11 @@
* @return The adjacent floating-point value closer to negative
* infinity.
* @author Joseph D. Darcy
+ * @deprecated Use Math.nextDown.
*/
+ @Deprecated
public static double nextDown(double d) {
- if( isNaN(d) || d == Double.NEGATIVE_INFINITY)
- return d;
- else {
- if (d == 0.0)
- return -Double.MIN_VALUE;
- else
- return Double.longBitsToDouble(Double.doubleToRawLongBits(d) +
- ((d > 0.0d)?-1L:+1L));
- }
+ return Math.nextDown(d);
}
/**
@@ -1022,17 +781,11 @@
* @return The adjacent floating-point value closer to negative
* infinity.
* @author Joseph D. Darcy
+ * @deprecated Use Math.nextDown.
*/
+ @Deprecated
public static double nextDown(float f) {
- if( isNaN(f) || f == Float.NEGATIVE_INFINITY)
- return f;
- else {
- if (f == 0.0f)
- return -Float.MIN_VALUE;
- else
- return Float.intBitsToFloat(Float.floatToRawIntBits(f) +
- ((f > 0.0f)?-1:+1));
- }
+ return Math.nextDown(f);
}
/**
@@ -1047,9 +800,11 @@
* and the sign of {@code sign}.
* @author Joseph D. Darcy
* @since 1.5
+ * @deprecated Use StrictMath.copySign.
*/
+ @Deprecated
public static double copySign(double magnitude, double sign) {
- return rawCopySign(magnitude, (isNaN(sign)?1.0d:sign));
+ return StrictMath.copySign(magnitude, sign);
}
/**
@@ -1063,9 +818,11 @@
* @return a value with the magnitude of {@code magnitude}
* and the sign of {@code sign}.
* @author Joseph D. Darcy
+ * @deprecated Use StrictMath.copySign.
*/
- public static float copySign(float magnitude, float sign) {
- return rawCopySign(magnitude, (isNaN(sign)?1.0f:sign));
+ @Deprecated
+ public static float copySign(float magnitude, float sign) {
+ return StrictMath.copySign(magnitude, sign);
}
/**
@@ -1090,33 +847,11 @@
* @return the size of an ulp of the argument
* @author Joseph D. Darcy
* @since 1.5
+ * @deprecated Use Math.ulp.
*/
+ @Deprecated
public static double ulp(double d) {
- int exp = getExponent(d);
-
- switch(exp) {
- case DoubleConsts.MAX_EXPONENT+1: // NaN or infinity
- return Math.abs(d);
-
- case DoubleConsts.MIN_EXPONENT-1: // zero or subnormal
- return Double.MIN_VALUE;
-
- default:
- assert exp <= DoubleConsts.MAX_EXPONENT && exp >= DoubleConsts.MIN_EXPONENT;
-
- // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
- exp = exp - (DoubleConsts.SIGNIFICAND_WIDTH-1);
- if (exp >= DoubleConsts.MIN_EXPONENT) {
- return powerOfTwoD(exp);
- }
- else {
- // return a subnormal result; left shift integer
- // representation of Double.MIN_VALUE appropriate
- // number of positions
- return Double.longBitsToDouble(1L <<
- (exp - (DoubleConsts.MIN_EXPONENT - (DoubleConsts.SIGNIFICAND_WIDTH-1)) ));
- }
- }
+ return Math.ulp(d);
}
/**
@@ -1141,33 +876,11 @@
* @return the size of an ulp of the argument
* @author Joseph D. Darcy
* @since 1.5
+ * @deprecated Use Math.ulp.
*/
+ @Deprecated
public static float ulp(float f) {
- int exp = getExponent(f);
-
- switch(exp) {
- case FloatConsts.MAX_EXPONENT+1: // NaN or infinity
- return Math.abs(f);
-
- case FloatConsts.MIN_EXPONENT-1: // zero or subnormal
- return FloatConsts.MIN_VALUE;
-
- default:
- assert exp <= FloatConsts.MAX_EXPONENT && exp >= FloatConsts.MIN_EXPONENT;
-
- // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x))
- exp = exp - (FloatConsts.SIGNIFICAND_WIDTH-1);
- if (exp >= FloatConsts.MIN_EXPONENT) {
- return powerOfTwoF(exp);
- }
- else {
- // return a subnormal result; left shift integer
- // representation of FloatConsts.MIN_VALUE appropriate
- // number of positions
- return Float.intBitsToFloat(1 <<
- (exp - (FloatConsts.MIN_EXPONENT - (FloatConsts.SIGNIFICAND_WIDTH-1)) ));
- }
- }
+ return Math.ulp(f);
}
/**
@@ -1186,9 +899,11 @@
* @return the signum function of the argument
* @author Joseph D. Darcy
* @since 1.5
+ * @deprecated Use Math.signum.
*/
+ @Deprecated
public static double signum(double d) {
- return (d == 0.0 || isNaN(d))?d:copySign(1.0, d);
+ return Math.signum(d);
}
/**
@@ -1207,9 +922,10 @@
* @return the signum function of the argument
* @author Joseph D. Darcy
* @since 1.5
+ * @deprecated Use Math.signum.
*/
+ @Deprecated
public static float signum(float f) {
- return (f == 0.0f || isNaN(f))?f:copySign(1.0f, f);
+ return Math.signum(f);
}
-
}
diff --git a/ojluni/src/main/java/sun/misc/Hashing.java b/ojluni/src/main/java/sun/misc/Hashing.java
deleted file mode 100644
index 2b3b144..0000000
--- a/ojluni/src/main/java/sun/misc/Hashing.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 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.misc;
-
-import java.util.concurrent.ThreadLocalRandom;
-
-/**
- * Hashing utilities.
- *
- * Little endian implementations of Murmur3 hashing.
- */
-public class Hashing {
-
- /**
- * Static utility methods only.
- */
- private Hashing() {
- throw new Error("No instances");
- }
-
- // Spread bits to regularize both segment and index locations,
- // using variant of single-word Wang/Jenkins hash.
- //
- // Based on commit 1424a2a1a9fc53dc8b859a77c02c924.
- public static int singleWordWangJenkinsHash(Object k) {
- int h = k.hashCode();
-
- h += (h << 15) ^ 0xffffcd7d;
- h ^= (h >>> 10);
- h += (h << 3);
- h ^= (h >>> 6);
- h += (h << 2) + (h << 14);
- return h ^ (h >>> 16);
- }
-}
diff --git a/ojluni/src/main/java/sun/misc/InvalidJarIndexException.java b/ojluni/src/main/java/sun/misc/InvalidJarIndexException.java
index 83e8199..44ca4ff 100644
--- a/ojluni/src/main/java/sun/misc/InvalidJarIndexException.java
+++ b/ojluni/src/main/java/sun/misc/InvalidJarIndexException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -38,6 +38,8 @@
public
class InvalidJarIndexException extends RuntimeException {
+ static final long serialVersionUID = -6159797516569680148L;
+
/**
* Constructs an <code>InvalidJarIndexException</code> with no
* detail message.
diff --git a/ojluni/src/main/java/sun/misc/JarIndex.java b/ojluni/src/main/java/sun/misc/JarIndex.java
index f9781d6..6e08cf2 100644
--- a/ojluni/src/main/java/sun/misc/JarIndex.java
+++ b/ojluni/src/main/java/sun/misc/JarIndex.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -26,9 +26,11 @@
package sun.misc;
import java.io.*;
+import java.security.AccessController;
import java.util.*;
import java.util.jar.*;
import java.util.zip.*;
+import sun.security.action.GetPropertyAction;
/**
* This class is used to maintain mappings from packages, classes
@@ -48,13 +50,13 @@
* The hash map that maintains mappings from
* package/classe/resource to jar file list(s)
*/
- private HashMap indexMap;
+ private HashMap<String,LinkedList<String>> indexMap;
/**
* The hash map that maintains mappings from
* jar file to package/class/resource lists
*/
- private HashMap jarMap;
+ private HashMap<String,LinkedList<String>> jarMap;
/*
* An ordered list of jar file names.
@@ -72,14 +74,15 @@
* be added to the index. Otherwise, just the directory names are added.
*/
private static final boolean metaInfFilenames =
- "true".equals(System.getProperty("sun.misc.JarIndex.metaInfFilenames"));
+ "true".equals(AccessController.doPrivileged(
+ new GetPropertyAction("sun.misc.JarIndex.metaInfFilenames")));
/**
* Constructs a new, empty jar index.
*/
public JarIndex() {
- indexMap = new HashMap();
- jarMap = new HashMap();
+ indexMap = new HashMap<>();
+ jarMap = new HashMap<>();
}
/**
@@ -150,10 +153,11 @@
* Add the key, value pair to the hashmap, the value will
* be put in a linked list which is created if necessary.
*/
- private void addToList(String key, String value, HashMap t) {
- LinkedList list = (LinkedList)t.get(key);
+ private void addToList(String key, String value,
+ HashMap<String,LinkedList<String>> t) {
+ LinkedList<String> list = t.get(key);
if (list == null) {
- list = new LinkedList();
+ list = new LinkedList<>();
list.add(value);
t.put(key, list);
} else if (!list.contains(value)) {
@@ -166,13 +170,13 @@
*
* @param fileName the key of the mapping
*/
- public LinkedList get(String fileName) {
- LinkedList jarFiles = null;
- if ((jarFiles = (LinkedList)indexMap.get(fileName)) == null) {
+ public LinkedList<String> get(String fileName) {
+ LinkedList<String> jarFiles = null;
+ if ((jarFiles = indexMap.get(fileName)) == null) {
/* try the package name again */
int pos;
if((pos = fileName.lastIndexOf("/")) != -1) {
- jarFiles = (LinkedList)indexMap.get(fileName.substring(0, pos));
+ jarFiles = indexMap.get(fileName.substring(0, pos));
}
}
return jarFiles;
@@ -200,23 +204,20 @@
packageName = fileName;
}
- // add the mapping to indexMap
- addToList(packageName, jarName, indexMap);
-
- // add the mapping to jarMap
- addToList(jarName, packageName, jarMap);
+ addMapping(packageName, jarName);
}
/**
* Same as add(String,String) except that it doesn't strip off from the
- * last index of '/'. It just adds the filename.
+ * last index of '/'. It just adds the jarItem (filename or package)
+ * as it is received.
*/
- private void addExplicit(String fileName, String jarName) {
+ private void addMapping(String jarItem, String jarName) {
// add the mapping to indexMap
- addToList(fileName, jarName, indexMap);
+ addToList(jarItem, jarName, indexMap);
// add the mapping to jarMap
- addToList(jarName, fileName, jarMap);
+ addToList(jarName, jarItem, jarMap);
}
/**
@@ -235,9 +236,9 @@
ZipFile zrf = new ZipFile(currentJar.replace
('/', File.separatorChar));
- Enumeration entries = zrf.entries();
+ Enumeration<? extends ZipEntry> entries = zrf.entries();
while(entries.hasMoreElements()) {
- ZipEntry entry = (ZipEntry) entries.nextElement();
+ ZipEntry entry = entries.nextElement();
String fileName = entry.getName();
// Skip the META-INF directory, the index, and manifest.
@@ -247,18 +248,14 @@
fileName.equals(JarFile.MANIFEST_NAME))
continue;
- if (!metaInfFilenames) {
+ if (!metaInfFilenames || !fileName.startsWith("META-INF/")) {
add(fileName, currentJar);
- } else {
- if (!fileName.startsWith("META-INF/")) {
- add(fileName, currentJar);
- } else if (!entry.isDirectory()) {
+ } else if (!entry.isDirectory()) {
// Add files under META-INF explicitly so that certain
// services, like ServiceLoader, etc, can be located
// with greater accuracy. Directories can be skipped
// since each file will be added explicitly.
- addExplicit(fileName, currentJar);
- }
+ addMapping(fileName, currentJar);
}
}
@@ -282,11 +279,11 @@
/* print out the jar file name */
String jar = jarFiles[i];
bw.write(jar + "\n");
- LinkedList jarlist = (LinkedList)jarMap.get(jar);
+ LinkedList<String> jarlist = jarMap.get(jar);
if (jarlist != null) {
- Iterator listitr = jarlist.iterator();
+ Iterator<String> listitr = jarlist.iterator();
while(listitr.hasNext()) {
- bw.write((String)(listitr.next()) + "\n");
+ bw.write(listitr.next() + "\n");
}
}
bw.write("\n");
@@ -309,7 +306,7 @@
String currentJar = null;
/* an ordered list of jar file names */
- Vector jars = new Vector();
+ Vector<String> jars = new Vector<>();
/* read until we see a .jar line */
while((line = br.readLine()) != null && !line.endsWith(".jar"));
@@ -323,12 +320,11 @@
jars.add(currentJar);
} else {
String name = line;
- addToList(name, currentJar, indexMap);
- addToList(currentJar, name, jarMap);
+ addMapping(name, currentJar);
}
}
- jarFiles = (String[])jars.toArray(new String[jars.size()]);
+ jarFiles = jars.toArray(new String[jars.size()]);
}
/**
@@ -342,18 +338,18 @@
*
*/
public void merge(JarIndex toIndex, String path) {
- Iterator itr = indexMap.entrySet().iterator();
+ Iterator<Map.Entry<String,LinkedList<String>>> itr = indexMap.entrySet().iterator();
while(itr.hasNext()) {
- Map.Entry e = (Map.Entry)itr.next();
- String packageName = (String)e.getKey();
- LinkedList from_list = (LinkedList)e.getValue();
- Iterator listItr = from_list.iterator();
+ Map.Entry<String,LinkedList<String>> e = itr.next();
+ String packageName = e.getKey();
+ LinkedList<String> from_list = e.getValue();
+ Iterator<String> listItr = from_list.iterator();
while(listItr.hasNext()) {
- String jarName = (String)listItr.next();
+ String jarName = listItr.next();
if (path != null) {
jarName = path.concat(jarName);
}
- toIndex.add(packageName, jarName);
+ toIndex.addMapping(packageName, jarName);
}
}
}
diff --git a/ojluni/src/main/java/sun/misc/LRUCache.java b/ojluni/src/main/java/sun/misc/LRUCache.java
index d4b9554..8c14c17 100644
--- a/ojluni/src/main/java/sun/misc/LRUCache.java
+++ b/ojluni/src/main/java/sun/misc/LRUCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -52,7 +52,9 @@
public V forName(N name) {
if (oa == null) {
- oa = (V[])new Object[size];
+ @SuppressWarnings("unchecked")
+ V[] temp = (V[])new Object[size];
+ oa = temp;
} else {
for (int i = 0; i < oa.length; i++) {
V ob = oa[i];
diff --git a/ojluni/src/main/java/sun/misc/MetaIndex.java b/ojluni/src/main/java/sun/misc/MetaIndex.java
index d2f7187..17481fb 100644
--- a/ojluni/src/main/java/sun/misc/MetaIndex.java
+++ b/ojluni/src/main/java/sun/misc/MetaIndex.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -71,7 +71,6 @@
org/w3c/
com/sun/imageio/
javax/
-sunw/util/
java/
sun/
...
diff --git a/ojluni/src/main/java/sun/misc/REException.java b/ojluni/src/main/java/sun/misc/REException.java
index 1799e82..db68992 100644
--- a/ojluni/src/main/java/sun/misc/REException.java
+++ b/ojluni/src/main/java/sun/misc/REException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -31,6 +31,9 @@
*/
public class REException extends Exception {
+
+ private static final long serialVersionUID = 4656584872733646963L;
+
REException (String s) {
super(s);
}
diff --git a/ojluni/src/main/java/sun/misc/SharedSecrets.java b/ojluni/src/main/java/sun/misc/SharedSecrets.java
index 0d0d744..d21aa4d 100644
--- a/ojluni/src/main/java/sun/misc/SharedSecrets.java
+++ b/ojluni/src/main/java/sun/misc/SharedSecrets.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -35,6 +35,7 @@
for this purpose, namely the loss of compile-time checking. */
public class SharedSecrets {
+ // BEGIN Android-changed: Pruned unused access interfaces
private static JavaIOFileDescriptorAccess javaIOFileDescriptorAccess;
public static void setJavaIOFileDescriptorAccess(JavaIOFileDescriptorAccess jiofda) {
@@ -44,4 +45,5 @@
public static JavaIOFileDescriptorAccess getJavaIOFileDescriptorAccess() {
return javaIOFileDescriptorAccess;
}
+ // END Android-changed: Pruned unused access interfaces
}
diff --git a/ojluni/src/main/java/sun/misc/URLClassPath.java b/ojluni/src/main/java/sun/misc/URLClassPath.java
index 5414547..e9a89bc 100644
--- a/ojluni/src/main/java/sun/misc/URLClassPath.java
+++ b/ojluni/src/main/java/sun/misc/URLClassPath.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1997, 2011, 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
@@ -44,6 +44,7 @@
import java.net.URLStreamHandler;
import java.net.URLStreamHandlerFactory;
import java.io.*;
+import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.AccessControlException;
import java.security.CodeSigner;
@@ -53,6 +54,7 @@
import java.security.cert.Certificate;
import sun.misc.FileURLMapper;
import sun.net.util.URLUtil;
+import sun.security.action.GetPropertyAction;
/**
* This class is used to maintain a search path of URLs for loading classes
@@ -64,16 +66,24 @@
final static String USER_AGENT_JAVA_VERSION = "UA-Java-Version";
final static String JAVA_VERSION;
private static final boolean DEBUG;
+ private static final boolean DEBUG_LOOKUP_CACHE;
private static final boolean DISABLE_JAR_CHECKING;
+ private static final boolean DISABLE_ACC_CHECKING;
static {
JAVA_VERSION = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("java.version"));
+ new GetPropertyAction("java.version"));
DEBUG = (java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
+ new GetPropertyAction("sun.misc.URLClassPath.debug")) != null);
+ DEBUG_LOOKUP_CACHE = (java.security.AccessController.doPrivileged(
+ new GetPropertyAction("sun.misc.URLClassPath.debugLookupCache")) != null);
String p = java.security.AccessController.doPrivileged(
- new sun.security.action.GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
+ new GetPropertyAction("sun.misc.URLClassPath.disableJarChecking"));
DISABLE_JAR_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
+
+ p = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.net.URLClassPath.disableRestrictedPermissions"));
+ DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
/* The original search path of URLs. */
@@ -94,6 +104,11 @@
/* Whether this URLClassLoader has been closed yet */
private boolean closed = false;
+ /* The context to be used when loading classes and resources. If non-null
+ * this is the context that was captured during the creation of the
+ * URLClassLoader. null implies no additional security restrictions. */
+ private final AccessControlContext acc;
+
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
@@ -103,8 +118,12 @@
* @param urls the directory and JAR file URLs to search for classes
* and resources
* @param factory the URLStreamHandlerFactory to use when creating new URLs
+ * @param acc the context to be used when loading classes and resources, may
+ * be null
*/
- public URLClassPath(URL[] urls, URLStreamHandlerFactory factory) {
+ public URLClassPath(URL[] urls,
+ URLStreamHandlerFactory factory,
+ AccessControlContext acc) {
for (int i = 0; i < urls.length; i++) {
path.add(urls[i]);
}
@@ -112,10 +131,22 @@
if (factory != null) {
jarHandler = factory.createURLStreamHandler("jar");
}
+ if (DISABLE_ACC_CHECKING)
+ this.acc = null;
+ else
+ this.acc = acc;
}
+ /**
+ * Constructs a URLClassPath with no additional security restrictions.
+ * Used by code that implements the class path.
+ */
public URLClassPath(URL[] urls) {
- this(urls, null);
+ this(urls, null, null);
+ }
+
+ public URLClassPath(URL[] urls, AccessControlContext acc) {
+ this(urls, null, acc);
}
public synchronized List<IOException> closeLoaders() {
@@ -150,6 +181,12 @@
urls.add(0, url);
path.add(url);
+
+ if (lookupCacheURLs != null) {
+ // The lookup cache is no longer valid, since getLookupCache()
+ // does not consider the newly added url.
+ disableAllLookupCaches();
+ }
}
}
@@ -173,7 +210,8 @@
*/
public URL findResource(String name, boolean check) {
Loader loader;
- for (int i = 0; (loader = getLoader(i)) != null; i++) {
+ int[] cache = getLookupCache(name);
+ for (int i = 0; (loader = getNextLoader(cache, i)) != null; i++) {
URL url = loader.findResource(name, check);
if (url != null) {
return url;
@@ -196,7 +234,8 @@
}
Loader loader;
- for (int i = 0; (loader = getLoader(i)) != null; i++) {
+ int[] cache = getLookupCache(name);
+ for (int i = 0; (loader = getNextLoader(cache, i)) != null; i++) {
Resource res = loader.getResource(name, check);
if (res != null) {
return res;
@@ -216,6 +255,7 @@
final boolean check) {
return new Enumeration<URL>() {
private int index = 0;
+ private int[] cache = getLookupCache(name);
private URL url = null;
private boolean next() {
@@ -223,7 +263,7 @@
return true;
} else {
Loader loader;
- while ((loader = getLoader(index++)) != null) {
+ while ((loader = getNextLoader(cache, index++)) != null) {
url = loader.findResource(name, check);
if (url != null) {
return true;
@@ -263,6 +303,7 @@
final boolean check) {
return new Enumeration<Resource>() {
private int index = 0;
+ private int[] cache = getLookupCache(name);
private Resource res = null;
private boolean next() {
@@ -270,7 +311,7 @@
return true;
} else {
Loader loader;
- while ((loader = getLoader(index++)) != null) {
+ while ((loader = getNextLoader(cache, index++)) != null) {
res = loader.getResource(name, check);
if (res != null) {
return true;
@@ -299,6 +340,170 @@
return getResources(name, true);
}
+ private static volatile boolean lookupCacheEnabled
+ // Android-changed: No lookup cache support.
+ // = "true".equals(VM.getSavedProperty("sun.cds.enableSharedLookupCache"));
+ = false;
+ private URL[] lookupCacheURLs;
+ private ClassLoader lookupCacheLoader;
+
+ synchronized void initLookupCache(ClassLoader loader) {
+ if ((lookupCacheURLs = getLookupCacheURLs(loader)) != null) {
+ lookupCacheLoader = loader;
+ } else {
+ // This JVM instance does not support lookup cache.
+ disableAllLookupCaches();
+ }
+ }
+
+ static void disableAllLookupCaches() {
+ lookupCacheEnabled = false;
+ }
+
+ // BEGIN Android-changed: No lookup chache support
+ /*
+ private static native URL[] getLookupCacheURLs(ClassLoader loader);
+ private static native int[] getLookupCacheForClassLoader(ClassLoader loader,
+ String name);
+ private static native boolean knownToNotExist0(ClassLoader loader,
+ String className);
+ */
+
+ private URL[] getLookupCacheURLs(ClassLoader loader) {
+ return null;
+ }
+ private static int[] getLookupCacheForClassLoader(ClassLoader loader,
+ String name) {
+ return null;
+ }
+ private static boolean knownToNotExist0(ClassLoader loader,
+ String className) {
+ return false;
+ }
+ // END Android-changed: No lookup chache support
+
+
+ synchronized boolean knownToNotExist(String className) {
+ if (lookupCacheURLs != null && lookupCacheEnabled) {
+ return knownToNotExist0(lookupCacheLoader, className);
+ }
+
+ // Don't know if this class exists or not -- need to do a full search.
+ return false;
+ }
+
+ /**
+ * Returns an array of the index to lookupCacheURLs that may
+ * contain the specified resource. The values in the returned
+ * array are in strictly ascending order and must be a valid index
+ * to lookupCacheURLs array.
+ *
+ * This method returns an empty array if the specified resource
+ * cannot be found in this URLClassPath. If there is no lookup
+ * cache or it's disabled, this method returns null and the lookup
+ * should search the entire classpath.
+ *
+ * Example: if lookupCacheURLs contains {a.jar, b.jar, c.jar, d.jar}
+ * and package "foo" only exists in a.jar and c.jar,
+ * getLookupCache("foo/Bar.class") will return {0, 2}
+ *
+ * @param name the resource name
+ * @return an array of the index to lookupCacheURLs that may contain the
+ * specified resource; or null if no lookup cache is used.
+ */
+ private synchronized int[] getLookupCache(String name) {
+ if (lookupCacheURLs == null || !lookupCacheEnabled) {
+ return null;
+ }
+
+ int[] cache = getLookupCacheForClassLoader(lookupCacheLoader, name);
+ if (cache != null && cache.length > 0) {
+ int maxindex = cache[cache.length - 1]; // cache[] is strictly ascending.
+ if (!ensureLoaderOpened(maxindex)) {
+ if (DEBUG_LOOKUP_CACHE) {
+ System.out.println("Expanded loaders FAILED " +
+ loaders.size() + " for maxindex=" + maxindex);
+ }
+ return null;
+ }
+ }
+
+ return cache;
+ }
+
+ private boolean ensureLoaderOpened(int index) {
+ if (loaders.size() <= index) {
+ // Open all Loaders up to, and including, index
+ if (getLoader(index) == null) {
+ return false;
+ }
+ if (!lookupCacheEnabled) {
+ // cache was invalidated as the result of the above call.
+ return false;
+ }
+ if (DEBUG_LOOKUP_CACHE) {
+ System.out.println("Expanded loaders " + loaders.size() +
+ " to index=" + index);
+ }
+ }
+ return true;
+ }
+
+ /*
+ * The CLASS-PATH attribute was expanded by the VM when building
+ * the resource lookup cache in the same order as the getLoader
+ * method does. This method validates if the URL from the lookup
+ * cache matches the URL of the Loader at the given index;
+ * otherwise, this method disables the lookup cache.
+ */
+ private synchronized void validateLookupCache(int index,
+ String urlNoFragString) {
+ if (lookupCacheURLs != null && lookupCacheEnabled) {
+ if (index < lookupCacheURLs.length &&
+ urlNoFragString.equals(
+ URLUtil.urlNoFragString(lookupCacheURLs[index]))) {
+ return;
+ }
+ if (DEBUG || DEBUG_LOOKUP_CACHE) {
+ System.out.println("WARNING: resource lookup cache invalidated "
+ + "for lookupCacheLoader at " + index);
+ }
+ disableAllLookupCaches();
+ }
+ }
+
+ /**
+ * Returns the next Loader that may contain the resource to
+ * lookup. If the given cache is null, return loaders.get(index)
+ * that may be lazily created; otherwise, cache[index] is the next
+ * Loader that may contain the resource to lookup and so returns
+ * loaders.get(cache[index]).
+ *
+ * If cache is non-null, loaders.get(cache[index]) must be present.
+ *
+ * @param cache lookup cache. If null, search the entire class path
+ * @param index index to the given cache array; or to the loaders list.
+ */
+ private synchronized Loader getNextLoader(int[] cache, int index) {
+ if (closed) {
+ return null;
+ }
+ if (cache != null) {
+ if (index < cache.length) {
+ Loader loader = loaders.get(cache[index]);
+ if (DEBUG_LOOKUP_CACHE) {
+ System.out.println("HASCACHE: Loading from : " + cache[index]
+ + " = " + loader.getBaseURL());
+ }
+ return loader;
+ } else {
+ return null; // finished iterating over cache[]
+ }
+ } else {
+ return getLoader(index);
+ }
+ }
+
/*
* Returns the Loader at the specified position in the URL search
* path. The URLs are opened and expanded as needed. Returns null
@@ -340,11 +545,23 @@
} catch (IOException e) {
// Silently ignore for now...
continue;
+ } catch (SecurityException se) {
+ // Always silently ignore. The context, if there is one, that
+ // this URLClassPath was given during construction will never
+ // have permission to access the URL.
+ if (DEBUG) {
+ System.err.println("Failed to access " + url + ", " + se );
+ }
+ continue;
}
// Finally, add the Loader to the search path.
+ validateLookupCache(loaders.size(), urlNoFragString);
loaders.add(loader);
lmap.put(urlNoFragString, loader);
}
+ if (DEBUG_LOOKUP_CACHE) {
+ System.out.println("NOCACHE: Loading from : " + index );
+ }
return loaders.get(index);
}
@@ -364,10 +581,10 @@
return new Loader(url);
}
} else {
- return new JarLoader(url, jarHandler, lmap);
+ return new JarLoader(url, jarHandler, lmap, acc);
}
}
- });
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -513,7 +730,8 @@
}
} else {
// our best guess for the other cases
- InputStream is = url.openStream();
+ uc.setUseCaches(false);
+ InputStream is = uc.getInputStream();
is.close();
}
return url;
@@ -591,25 +809,31 @@
*/
static class JarLoader extends Loader {
private JarFile jar;
- private URL csu;
+ private final URL csu;
private JarIndex index;
private MetaIndex metaIndex;
private URLStreamHandler handler;
- private HashMap<String, Loader> lmap;
+ private final HashMap<String, Loader> lmap;
+ private final AccessControlContext acc;
private boolean closed = false;
+ // Android-changed: Not needed, called directly
+ // private static final sun.misc.JavaUtilZipFileAccess zipAccess =
+ // sun.misc.SharedSecrets.getJavaUtilZipFileAccess();
/*
* Creates a new JarLoader for the specified URL referring to
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
- HashMap<String, Loader> loaderMap)
+ HashMap<String, Loader> loaderMap,
+ AccessControlContext acc)
throws IOException
{
super(new URL("jar", "", -1, url + "!/", jarHandler));
csu = url;
handler = jarHandler;
lmap = loaderMap;
+ this.acc = acc;
if (!isOptimizable(url)) {
ensureOpen();
@@ -693,8 +917,7 @@
}
return null;
}
- }
- );
+ }, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
@@ -739,7 +962,7 @@
try {
ensureOpen();
} catch (IOException e) {
- throw (InternalError) new InternalError().initCause(e);
+ throw new InternalError(e);
}
return index;
}
@@ -834,7 +1057,7 @@
try {
ensureOpen();
} catch (IOException e) {
- throw (InternalError) new InternalError().initCause(e);
+ throw new InternalError(e);
}
final JarEntry entry = jar.getJarEntry(name);
if (entry != null)
@@ -858,10 +1081,9 @@
Set<String> visited) {
Resource res;
- Object[] jarFiles;
- boolean done = false;
+ String[] jarFiles;
int count = 0;
- LinkedList jarFilesList = null;
+ LinkedList<String> jarFilesList = null;
/* If there no jar files in the index that can potential contain
* this resource then return immediately.
@@ -870,11 +1092,11 @@
return null;
do {
- jarFiles = jarFilesList.toArray();
int size = jarFilesList.size();
+ jarFiles = jarFilesList.toArray(new String[size]);
/* loop through the mapped jar file list */
while(count < size) {
- String jarName = (String)jarFiles[count++];
+ String jarName = jarFiles[count++];
JarLoader newLoader;
final URL url;
@@ -889,9 +1111,9 @@
new PrivilegedExceptionAction<JarLoader>() {
public JarLoader run() throws IOException {
return new JarLoader(url, handler,
- lmap);
+ lmap, acc);
}
- });
+ }, acc);
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
@@ -922,7 +1144,7 @@
try {
newLoader.ensureOpen();
} catch (IOException e) {
- throw (InternalError) new InternalError().initCause(e);
+ throw new InternalError(e);
}
final JarEntry entry = newLoader.jar.getJarEntry(name);
if (entry != null) {
@@ -999,6 +1221,8 @@
* parse the standard extension dependencies
*/
private void parseExtensionsDependencies() throws IOException {
+ // Android-changed: checkExtensionsDependencies(jar) is not supported on Android.
+ //ExtensionDependency.checkExtensionsDependencies(jar);
}
/*
diff --git a/ojluni/src/main/java/sun/misc/VM.java b/ojluni/src/main/java/sun/misc/VM.java
index b57eb4a..f9060ba 100644
--- a/ojluni/src/main/java/sun/misc/VM.java
+++ b/ojluni/src/main/java/sun/misc/VM.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -48,6 +48,7 @@
return suspended;
}
+ @SuppressWarnings("deprecation")
public static boolean allowThreadSuspension(ThreadGroup g, boolean b) {
return g.allowThreadSuspension(b);
}
@@ -92,6 +93,11 @@
return STATE_GREEN;
}
+ // Android-removed: Not used
+ /** @deprecated */
+ // @Deprecated
+ // public static void registerVMNotification(VMNotification n) { }
+
/** @deprecated */
@Deprecated
public static void asChange(int as_old, int as_new) { }
@@ -143,6 +149,7 @@
private static volatile boolean booted = false;
+ private static final Object lock = new Object();
// Invoked by by System.initializeSystemClass just before returning.
// Subsystems that are invoked during initialization can check this
@@ -150,20 +157,34 @@
// application class loader has been set up.
//
public static void booted() {
- booted = true;
+ synchronized (lock) {
+ booted = true;
+ lock.notifyAll();
+ }
}
public static boolean isBooted() {
return booted;
}
+ // Waits until VM completes initialization
+ //
+ // This method is invoked by the Finalizer thread
+ public static void awaitBooted() throws InterruptedException {
+ synchronized (lock) {
+ while (!booted) {
+ lock.wait();
+ }
+ }
+ }
+
// A user-settable upper limit on the maximum amount of allocatable direct
// buffer memory. This value may be changed during VM initialization if
// "java" is launched with "-XX:MaxDirectMemorySize=<size>".
//
// The initial value of this field is arbitrary; during JRE initialization
// it will be reset to the value specified on the command line, if any,
- // otherwise to Runtime.getRuntime.maxDirectMemory().
+ // otherwise to Runtime.getRuntime().maxMemory().
//
private static long directMemory = 64 * 1024 * 1024;
@@ -212,16 +233,15 @@
return allowArraySyntax;
}
- private static boolean allowGetCallerClass = true;
-
- // Reflection.getCallerClass(int) is enabled by default.
- // It can be disabled by setting the system property
- // "jdk.reflect.allowGetCallerClass" to "false". It cannot be
- // disabled if the logging stack walk (to find resource bundles)
- // is enabled.
- public static boolean allowGetCallerClass() {
- return allowGetCallerClass;
- }
+ // BEGIN Android-removed: Not used on android
+ /**
+ * Returns true if the given class loader is in the system domain
+ * in which all permissions are granted.
+ */
+ // public static boolean isSystemDomainLoader(ClassLoader loader) {
+ // return loader == null;
+ // }
+ // END Android-removed: Not used on android
/**
* Returns the system property of the specified key saved at
@@ -288,15 +308,6 @@
? defaultAllowArraySyntax
: Boolean.parseBoolean(s));
- // Reflection.getCallerClass(int) is enabled by default.
- // It can be disabled by setting a system property (but only if
- // the logging stack walk is not enabled)
- s = props.getProperty("jdk.reflect.allowGetCallerClass");
- allowGetCallerClass = (s != null
- ? (s.isEmpty() || Boolean.parseBoolean(s))
- : true) ||
- Boolean.parseBoolean(props.getProperty("jdk.logging.allowStackWalkSearch"));
-
// Remove other private system properties
// used by java.lang.Integer.IntegerCache
props.remove("java.lang.Integer.IntegerCache.high");
@@ -306,12 +317,19 @@
// used by sun.launcher.LauncherHelper
props.remove("sun.java.launcher.diag");
+
+ // used by sun.misc.URLClassPath
+ props.remove("sun.cds.enableSharedLookupCache");
}
// Initialize any miscellenous operating system settings that need to be
// set for the class libraries.
//
public static void initializeOSEnvironment() {
+ // Android-removed: OSEnvironment.initialize() not supported
+ //if (!booted) {
+ // OSEnvironment.initialize();
+ //}
}
/* Current count of objects pending for finalization */
@@ -384,4 +402,17 @@
private final static int JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER = 0x0400;
private final static int JVMTI_THREAD_STATE_WAITING_INDEFINITELY = 0x0010;
private final static int JVMTI_THREAD_STATE_WAITING_WITH_TIMEOUT = 0x0020;
+
+ // BEGIN Android-removed: latestUserDefinedLoader()/initialize() not supported
+ // /*
+ // * Returns the first non-null class loader up the execution stack,
+ // * or null if only code from the null class loader is on the stack.
+ // */
+ // public static native ClassLoader latestUserDefinedLoader();
+
+ // static {
+ // initialize();
+ // }
+ // private native static void initialize();
+ // END Android-removed: latestUserDefinedLoader()/initialize() not supported
}
diff --git a/ojluni/src/main/java/sun/misc/Version.java b/ojluni/src/main/java/sun/misc/Version.java
index 6ea3823..3ac6a91 100644
--- a/ojluni/src/main/java/sun/misc/Version.java
+++ b/ojluni/src/main/java/sun/misc/Version.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -33,6 +33,7 @@
private static final String launcher_name = "";
private static final String java_version = AndroidHardcodedSystemProperties.JAVA_VERSION;
private static final String java_runtime_name = "Android Runtime";
+ private static final String java_profile_name = "";
private static final String java_runtime_version = "0.9";
// Called by java.lang.System.<clinit>
@@ -81,23 +82,28 @@
boolean isHeadless = false;
/* Report that we're running headless if the property is true */
- String headless = System.getProperty("java.awt.headless");
- if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
+ String headless = System.getProperty("java.awt.headless");
+ if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) {
isHeadless = true;
- }
+ }
/* First line: platform version. */
ps.println(launcher_name + " version \"" + java_version + "\"");
/* Second line: runtime version (ie, libraries). */
- ps.print(java_runtime_name + " (build " + java_runtime_version);
+ ps.print(java_runtime_name + " (build " + java_runtime_version);
- if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
- // embedded builds report headless state
- ps.print(", headless");
- }
- ps.println(')');
+ if (java_profile_name.length() > 0) {
+ // profile name
+ ps.print(", profile " + java_profile_name);
+ }
+
+ if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) {
+ // embedded builds report headless state
+ ps.print(", headless");
+ }
+ ps.println(')');
/* Third line: JVM information. */
String java_vm_name = System.getProperty("java.vm.name");
@@ -274,15 +280,24 @@
jvm_minor_version = Character.digit(cs.charAt(2), 10);
jvm_micro_version = Character.digit(cs.charAt(4), 10);
cs = cs.subSequence(5, cs.length());
- if (cs.charAt(0) == '_' && cs.length() >= 3 &&
- Character.isDigit(cs.charAt(1)) &&
- Character.isDigit(cs.charAt(2))) {
- int nextChar = 3;
+ if (cs.charAt(0) == '_' && cs.length() >= 3) {
+ int nextChar = 0;
+ if (Character.isDigit(cs.charAt(1)) &&
+ Character.isDigit(cs.charAt(2)) &&
+ Character.isDigit(cs.charAt(3)))
+ {
+ nextChar = 4;
+ } else if (Character.isDigit(cs.charAt(1)) &&
+ Character.isDigit(cs.charAt(2)))
+ {
+ nextChar = 3;
+ }
+
try {
- String uu = cs.subSequence(1, 3).toString();
- jvm_update_version = Integer.parseInt(uu);
- if (cs.length() >= 4) {
- char c = cs.charAt(3);
+ String uu = cs.subSequence(1, nextChar).toString();
+ jvm_update_version = Integer.valueOf(uu).intValue();
+ if (cs.length() >= nextChar + 1) {
+ char c = cs.charAt(nextChar);
if (c >= 'a' && c <= 'z') {
jvm_special_version = Character.toString(c);
nextChar++;
@@ -305,7 +320,7 @@
Character.isDigit(s.charAt(1)) &&
Character.isDigit(s.charAt(2))) {
jvm_build_number =
- Integer.parseInt(s.substring(1, 3));
+ Integer.valueOf(s.substring(1, 3)).intValue();
break;
}
}
@@ -322,7 +337,6 @@
// Return false if not available which implies an old VM (Tiger or before).
private static native boolean getJvmVersionInfo();
private static native void getJdkVersionInfo();
-
}
// Help Emacs a little because this file doesn't end in .java.
diff --git a/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java b/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java
index 94005e0..0b58a99 100644
--- a/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java
+++ b/ojluni/src/main/java/sun/net/ExtendedOptionsImpl.java
@@ -43,6 +43,17 @@
*/
public class ExtendedOptionsImpl {
+ // Android-removed: System.loadLibrary("net") is not available on Android.
+ /*
+ static {
+ AccessController.doPrivileged((PrivilegedAction<Void>)() -> {
+ System.loadLibrary("net");
+ return null;
+ });
+ init();
+ }
+ */
+
private ExtendedOptionsImpl() {}
public static void checkSetOptionPermission(SocketOption<?> option) {
@@ -71,6 +82,9 @@
}
}
+ // Android-removed: Native initialization logic that doesn't exist on Android.
+ // private static native void init();
+
/*
* Extension native implementations
*
diff --git a/ojluni/src/main/java/sun/net/NetHooks.java b/ojluni/src/main/java/sun/net/NetHooks.java
index 05100d9..153096e 100644
--- a/ojluni/src/main/java/sun/net/NetHooks.java
+++ b/ojluni/src/main/java/sun/net/NetHooks.java
@@ -38,43 +38,45 @@
public final class NetHooks {
- // Android-removed: No SDP support.
- // /**
- // * A provider with hooks to allow sockets be converted prior to binding or
- // * connecting a TCP socket.
- // *
- // * <p> Concrete implementations of this class should define a zero-argument
- // * constructor and implement the abstract methods specified below.
- // */
- // public static abstract class Provider {
- // /**
- // * Initializes a new instance of this class.
- // */
- // protected Provider() {}
- //
- // /**
- // * Invoked prior to binding a TCP socket.
- // */
- // public abstract void implBeforeTcpBind(FileDescriptor fdObj,
- // InetAddress address,
- // int port)
- // throws IOException;
- //
- // /**
- // * Invoked prior to connecting an unbound TCP socket.
- // */
- // public abstract void implBeforeTcpConnect(FileDescriptor fdObj,
- // InetAddress address,
- // int port)
- // throws IOException;
- // }
+ // Android-removed: Android doesn't support Session Description Protocol (SDP).
+ /*
+ /**
+ * A provider with hooks to allow sockets be converted prior to binding or
+ * connecting a TCP socket.
+ *
+ * <p> Concrete implementations of this class should define a zero-argument
+ * constructor and implement the abstract methods specified below.
+ *
+ public static abstract class Provider {
+ /**
+ * Initializes a new instance of this class.
+ *
+ protected Provider() {}
+
+ /**
+ * Invoked prior to binding a TCP socket.
+ *
+ public abstract void implBeforeTcpBind(FileDescriptor fdObj,
+ InetAddress address,
+ int port)
+ throws IOException;
+
+ /**
+ * Invoked prior to connecting an unbound TCP socket.
+ *
+ public abstract void implBeforeTcpConnect(FileDescriptor fdObj,
+ InetAddress address,
+ int port)
+ throws IOException;
+ }
+ */
/**
* For now, we load the SDP provider on Solaris. In the future this may
* be changed to use the ServiceLoader facility to allow the deployment of
* other providers.
*/
- // Android-removed: No SDP support
+ // Android-removed: Android doesn't support Session Description Protocol (SDP).
// private static final Provider provider = new sun.net.sdp.SdpProvider();
/**
@@ -85,7 +87,7 @@
int port)
throws IOException
{
- // Android-removed: No SDP support
+ // Android-removed: Android doesn't support Session Description Protocol (SDP).
// provider.implBeforeTcpBind(fdObj, address, port);
}
diff --git a/ojluni/src/main/java/sun/net/NetworkClient.java b/ojluni/src/main/java/sun/net/NetworkClient.java
index 1b311bc..0f76bf6 100644
--- a/ojluni/src/main/java/sun/net/NetworkClient.java
+++ b/ojluni/src/main/java/sun/net/NetworkClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -139,7 +139,7 @@
serverSocket.getOutputStream()),
true, encoding);
} catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding +"encoding not found");
+ throw new InternalError(encoding +"encoding not found", e);
}
serverInput = new BufferedInputStream(serverSocket.getInputStream());
}
@@ -244,7 +244,7 @@
* Sets the read timeout.
*
* Note: Public URLConnection (and protocol specific implementations)
- * protect against negative timeout values being set. This implemenation,
+ * protect against negative timeout values being set. This implementation,
* and protocol specific implementations, use -1 to represent the default
* read timeout.
*
diff --git a/ojluni/src/main/java/sun/net/TelnetOutputStream.java b/ojluni/src/main/java/sun/net/TelnetOutputStream.java
index 432e975..74f6c9c 100644
--- a/ojluni/src/main/java/sun/net/TelnetOutputStream.java
+++ b/ojluni/src/main/java/sun/net/TelnetOutputStream.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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
@@ -81,7 +81,7 @@
}
/**
- * set the stickyCRLF flag. Tells wether the terminal considers CRLF as a single
+ * set the stickyCRLF flag. Tells whether the terminal considers CRLF as a single
* char.
*
* @param on the <code>boolean</code> to set the flag to.
diff --git a/ojluni/src/main/java/sun/net/ftp/FtpClient.java b/ojluni/src/main/java/sun/net/ftp/FtpClient.java
index 3e9f385..73df120 100644
--- a/ojluni/src/main/java/sun/net/ftp/FtpClient.java
+++ b/ojluni/src/main/java/sun/net/ftp/FtpClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -267,7 +267,7 @@
* @param user The user name
* @param password The password for that user
* @return this FtpClient
- * @throws IOException if an error occured during the transmission
+ * @throws IOException if an error occurred during the transmission
* @throws FtpProtocolException if the login was refused by the server
*/
public abstract FtpClient login(String user, char[] password) throws FtpProtocolException, IOException;
@@ -378,7 +378,7 @@
*
* @param name the name of the remote file
* @return the {@link java.io.InputStream} from the data connection
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was refused by the server
* @see #setRestartOffset(long)
*/
@@ -398,7 +398,7 @@
* @param name the name of the remote file to write.
* @return the {@link java.io.OutputStream} from the data connection or
* {@code null} if the command was unsuccessful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public OutputStream putFileStream(String name) throws FtpProtocolException, IOException {
@@ -427,7 +427,7 @@
* @param unique {@code true} if the remote files should be unique,
* in which case the STOU command will be used.
* @return the {@link java.io.OutputStream} from the data connection.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract OutputStream putFileStream(String name, boolean unique) throws FtpProtocolException, IOException;
@@ -456,7 +456,7 @@
* @param local the {@code InputStream} that points to the data to
* transfer.
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public FtpClient putFile(String name, InputStream local) throws FtpProtocolException, IOException {
@@ -481,7 +481,7 @@
* @param unique {@code true} if the remote file should be unique
* (i.e. not already existing), {@code false} otherwise.
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
* @see #getLastFileName()
*/
@@ -500,7 +500,7 @@
* @param local The {@code InputStream} providing access to the data
* to be appended.
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient appendFile(String name, InputStream local) throws FtpProtocolException, IOException;
@@ -511,7 +511,7 @@
* @param from the name of the file being renamed
* @param to the new name for the file
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient rename(String from, String to) throws FtpProtocolException, IOException;
@@ -522,7 +522,7 @@
* @param name a {@code String} containing the name of the file
* to delete.
* @return this FtpClient
- * @throws IOException if an error occured during the exchange
+ * @throws IOException if an error occurred during the exchange
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient deleteFile(String name) throws FtpProtocolException, IOException;
@@ -533,7 +533,7 @@
* @param name a {@code String} containing the name of the directory
* to create.
* @return this FtpClient
- * @throws IOException if an error occured during the exchange
+ * @throws IOException if an error occurred during the exchange
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient makeDirectory(String name) throws FtpProtocolException, IOException;
@@ -545,7 +545,7 @@
* to remove.
*
* @return this FtpClient
- * @throws IOException if an error occured during the exchange.
+ * @throws IOException if an error occurred during the exchange.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient removeDirectory(String name) throws FtpProtocolException, IOException;
@@ -555,7 +555,7 @@
* status or as a <I>keep alive</I> mechanism.
*
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient noop() throws FtpProtocolException, IOException;
@@ -572,7 +572,7 @@
* @param name an optional {@code String} containing the pathname
* the STAT command should apply to.
* @return the response from the server
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract String getStatus(String name) throws FtpProtocolException, IOException;
@@ -602,7 +602,7 @@
* after an abort.</p>
*
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient abort() throws FtpProtocolException, IOException;
@@ -637,7 +637,7 @@
* </pre>
* <p>Since {@link #close()} will call completePending() if necessary.</p>
* @return this FtpClient
- * @throws IOException if an error occured during the transfer
+ * @throws IOException if an error occurred during the transfer
* @throws FtpProtocolException if the command didn't complete successfully
*/
public abstract FtpClient completePending() throws FtpProtocolException, IOException;
@@ -786,7 +786,7 @@
* for the current working directoty.
* @return a {@code Iterator} of files or {@code null} if the
* command failed.
- * @throws IOException if an error occured during the transmission
+ * @throws IOException if an error occurred during the transmission
* @see #setDirParser(FtpDirParser)
* @see #changeDirectory(String)
* @throws FtpProtocolException if the command was rejected by the server
@@ -862,7 +862,7 @@
* but before calling {@link #login(java.lang.String, char[]) }.</p>
*
* @return this FtpCLient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
* @see #endSecureSession()
*/
@@ -874,7 +874,7 @@
* back to a non encrypted transmission.
*
* @return this FtpClient
- * @throws IOException if an error occured during transmission.
+ * @throws IOException if an error occurred during transmission.
* @throws FtpProtocolException if the command was rejected by the server
* @see #startSecureSession()
*/
@@ -886,7 +886,7 @@
*
* @param size The number of bytes to allocate.
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient allocate(long size) throws FtpProtocolException, IOException;
@@ -899,7 +899,7 @@
* @param struct a {@code String} containing the name of the
* structure to mount.
* @return this FtpClient
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient structureMount(String struct) throws FtpProtocolException, IOException;
@@ -911,7 +911,7 @@
*
* @return a {@code String} describing the OS, or {@code null}
* if the operation was not successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract String getSystem() throws FtpProtocolException, IOException;
@@ -924,7 +924,7 @@
* {@code null} for the general help
* @return a {@code String} containing the text sent back by the
* server, or {@code null} if the command failed.
- * @throws IOException if an error occured during transmission
+ * @throws IOException if an error occurred during transmission
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract String getHelp(String cmd) throws FtpProtocolException, IOException;
@@ -936,7 +936,7 @@
*
* @param cmd the command to be sent.
* @return this FtpClient
- * @throws IOException if an error occured during transmission
+ * @throws IOException if an error occurred during transmission
* @throws FtpProtocolException if the command was rejected by the server
*/
public abstract FtpClient siteCmd(String cmd) throws FtpProtocolException, IOException;
diff --git a/ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java b/ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java
index 71cd134..06deae6 100644
--- a/ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java
+++ b/ojluni/src/main/java/sun/net/ftp/FtpClientProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -27,7 +27,7 @@
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ServiceConfigurationError;
-//import sun.misc.Service;
+//import java.util.ServiceLoader;
/**
* Service provider class for FtpClient.
@@ -67,35 +67,34 @@
return false;
}
try {
- Class c = Class.forName(cm, true, null);
+ Class<?> c = Class.forName(cm, true, null);
provider = (FtpClientProvider) c.newInstance();
return true;
- } catch (ClassNotFoundException x) {
- throw new ServiceConfigurationError(x.toString());
- } catch (IllegalAccessException x) {
- throw new ServiceConfigurationError(x.toString());
- } catch (InstantiationException x) {
- throw new ServiceConfigurationError(x.toString());
- } catch (SecurityException x) {
+ } catch (ClassNotFoundException |
+ IllegalAccessException |
+ InstantiationException |
+ SecurityException x) {
throw new ServiceConfigurationError(x.toString());
}
}
private static boolean loadProviderAsService() {
- // Iterator i = Service.providers(FtpClientProvider.class,
- // ClassLoader.getSystemClassLoader());
- // while (i.hasNext()) {
- // try {
- // provider = (FtpClientProvider) i.next();
- // return true;
- // } catch (ServiceConfigurationError sce) {
- // if (sce.getCause() instanceof SecurityException) {
- // // Ignore, try next provider, if any
- // continue;
- // }
- // throw sce;
- // }
- // }
+// Iterator<FtpClientProvider> i =
+// ServiceLoader.load(FtpClientProvider.class,
+// ClassLoader.getSystemClassLoader()).iterator();
+//
+// while (i.hasNext()) {
+// try {
+// provider = i.next();
+// return true;
+// } catch (ServiceConfigurationError sce) {
+// if (sce.getCause() instanceof SecurityException) {
+// // Ignore, try next provider, if any
+// continue;
+// }
+// throw sce;
+// }
+// }
return false;
}
diff --git a/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java b/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
index fea9421..0c117d4 100644
--- a/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
+++ b/ojluni/src/main/java/sun/net/ftp/impl/FtpClient.java
@@ -28,7 +28,6 @@
import java.io.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.security.PrivilegedExceptionAction;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -431,7 +430,7 @@
}
response = replyBuf.toString();
replyBuf.setLength(0);
- if (logger.isLoggable(PlatformLogger.FINEST)) {
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
logger.finest("Server [" + serverAddr + "] --> " + response);
}
@@ -473,7 +472,7 @@
/** Sends command <i>cmd</i> to the server. */
private void sendServer(String cmd) {
out.print(cmd);
- if (logger.isLoggable(PlatformLogger.FINEST)) {
+ if (logger.isLoggable(PlatformLogger.Level.FINEST)) {
logger.finest("Server [" + serverAddr + "] <-- " + cmd);
}
}
@@ -492,7 +491,7 @@
* Read the reply from the FTP server.
*
* @return <code>true</code> if the command was successful
- * @throws IOException if an error occured
+ * @throws IOException if an error occurred
*/
private boolean readReply() throws IOException {
lastReplyCode = FtpReplyCode.find(readServerResponse());
@@ -545,7 +544,7 @@
*
* @param cmd String containing the command
*
- * @throws FtpProtocolException if an error occured
+ * @throws FtpProtocolException if an error occurred
*/
private void issueCommandCheck(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
if (!issueCommand(cmd)) {
@@ -668,7 +667,6 @@
// Bind the socket to the same address as the control channel. This
// is needed in case of multi-homed systems.
s.bind(new InetSocketAddress(serverAddress, 0));
-
if (connectTimeout >= 0) {
s.connect(dest, connectTimeout);
} else {
@@ -747,7 +745,7 @@
// Some FTP servers (like the one on Solaris) are bugged, they
// will accept the EPRT command but then, the subsequent command
// (e.g. RETR) will fail, so we have to check BOTH results (the
- // EPRT cmd then the actual command) to decide wether we should
+ // EPRT cmd then the actual command) to decide whether we should
// fall back on the older PORT command.
portCmd = "EPRT |" + ((myAddress instanceof Inet6Address) ? "2" : "1") + "|" +
myAddress.getHostAddress() + "|" + portSocket.getLocalPort() + "|";
@@ -837,6 +835,7 @@
* @see #setActiveMode()
*/
public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) {
+
// Only passive mode used in JDK. See Bug 8010784.
// passiveMode = passive;
return this;
@@ -927,7 +926,7 @@
out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
true, encoding);
} catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding + "encoding not found");
+ throw new InternalError(encoding + "encoding not found", e);
}
in = new BufferedInputStream(server.getInputStream());
}
@@ -1045,7 +1044,7 @@
* @param user The user name
* @param password The password for that user
* @return <code>true</code> if the login was successful.
- * @throws IOException if an error occured during the transmission
+ * @throws IOException if an error occurred during the transmission
*/
public sun.net.ftp.FtpClient login(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException {
if (!isConnected()) {
@@ -1273,7 +1272,7 @@
* @param name the name of the remote file
* @return the {@link java.io.InputStream} from the data connection, or
* <code>null</code> if the command was unsuccessful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public InputStream getFileStream(String name) throws sun.net.ftp.FtpProtocolException, IOException {
Socket s;
@@ -1322,7 +1321,7 @@
* in which case the STOU command will be used.
* @return the {@link java.io.OutputStream} from the data connection or
* <code>null</code> if the command was unsuccessful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public OutputStream putFileStream(String name, boolean unique)
throws sun.net.ftp.FtpProtocolException, IOException
@@ -1351,7 +1350,7 @@
* @param unique <code>true</code> if the remote file should be unique
* (i.e. not already existing), <code>false</code> otherwise.
* @return <code>true</code> if the transfer was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @see #getLastFileName()
*/
public sun.net.ftp.FtpClient putFile(String name, InputStream local, boolean unique) throws sun.net.ftp.FtpProtocolException, IOException {
@@ -1382,7 +1381,7 @@
* @param local The <code>InputStream</code> providing access to the data
* to be appended.
* @return <code>true</code> if the transfer was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public sun.net.ftp.FtpClient appendFile(String name, InputStream local) throws sun.net.ftp.FtpProtocolException, IOException {
int mtu = 1500;
@@ -1418,7 +1417,7 @@
* @param name a <code>String</code> containing the name of the file
* to delete.
* @return <code>true</code> if the command was successful
- * @throws IOException if an error occured during the exchange
+ * @throws IOException if an error occurred during the exchange
*/
public sun.net.ftp.FtpClient deleteFile(String name) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("DELE " + name);
@@ -1431,7 +1430,7 @@
* @param name a <code>String</code> containing the name of the directory
* to create.
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during the exchange
+ * @throws IOException if an error occurred during the exchange
*/
public sun.net.ftp.FtpClient makeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("MKD " + name);
@@ -1445,7 +1444,7 @@
* to remove.
*
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during the exchange.
+ * @throws IOException if an error occurred during the exchange.
*/
public sun.net.ftp.FtpClient removeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("RMD " + name);
@@ -1476,7 +1475,7 @@
* the STAT command should apply to.
* @return the response from the server or <code>null</code> if the
* command failed.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public String getStatus(String name) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck((name == null ? "STAT" : "STAT " + name));
@@ -1559,7 +1558,7 @@
* It tells the server to stop the previous command or transfer.
*
* @return <code>true</code> if the command was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public sun.net.ftp.FtpClient abort() throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("ABOR");
@@ -1646,7 +1645,7 @@
out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
true, encoding);
} catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding + "encoding not found");
+ throw new InternalError(encoding + "encoding not found", e);
}
in = new BufferedInputStream(server.getInputStream());
}
@@ -1719,7 +1718,7 @@
*/
public InputStream nameList(String path) throws sun.net.ftp.FtpProtocolException, IOException {
Socket s;
- s = openDataConnection("NLST " + path);
+ s = openDataConnection(path == null ? "NLST" : "NLST " + path);
if (s != null) {
return createInputStream(s.getInputStream());
}
@@ -1882,7 +1881,7 @@
* for the current working directoty.
* @return a <code>Iterator</code> of files or <code>null</code> if the
* command failed.
- * @throws IOException if an error occured during the transmission
+ * @throws IOException if an error occurred during the transmission
* @see #setDirParser(FtpDirParser)
* @see #changeDirectory(String)
*/
@@ -2050,7 +2049,7 @@
* {@link #reInit()} command or a {@link #endSecureSession()} command is issued.
*
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
* @see #endSecureSession()
*/
public sun.net.ftp.FtpClient startSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
@@ -2082,7 +2081,7 @@
out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
true, encoding);
} catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding + "encoding not found");
+ throw new InternalError(encoding + "encoding not found", e);
}
in = new BufferedInputStream(server.getInputStream());
@@ -2098,7 +2097,7 @@
* back to a non crypted transmission.
*
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during transmission.
+ * @throws IOException if an error occurred during transmission.
* @see #startSecureSession()
*/
public sun.net.ftp.FtpClient endSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
@@ -2116,7 +2115,7 @@
out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
true, encoding);
} catch (UnsupportedEncodingException e) {
- throw new InternalError(encoding + "encoding not found");
+ throw new InternalError(encoding + "encoding not found", e);
}
in = new BufferedInputStream(server.getInputStream());
@@ -2129,7 +2128,7 @@
*
* @param size The number of bytes to allocate.
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public sun.net.ftp.FtpClient allocate(long size) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("ALLO " + size);
@@ -2144,7 +2143,7 @@
* @param struct a <code>String</code> containing the name of the
* structure to mount.
* @return <code>true</code> if the operation was successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public sun.net.ftp.FtpClient structureMount(String struct) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("SMNT " + struct);
@@ -2158,7 +2157,7 @@
*
* @return a <code>String</code> describing the OS, or <code>null</code>
* if the operation was not successful.
- * @throws IOException if an error occured during the transmission.
+ * @throws IOException if an error occurred during the transmission.
*/
public String getSystem() throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("SYST");
@@ -2178,7 +2177,7 @@
* <code>null</code> for the general help
* @return a <code>String</code> containing the text sent back by the
* server, or <code>null</code> if the command failed.
- * @throws IOException if an error occured during transmission
+ * @throws IOException if an error occurred during transmission
*/
public String getHelp(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("HELP " + cmd);
@@ -2221,7 +2220,7 @@
*
* @param cmd the command to be sent.
* @return <code>true</code> if the command was successful.
- * @throws IOException if an error occured during transmission
+ * @throws IOException if an error occurred during transmission
*/
public sun.net.ftp.FtpClient siteCmd(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
issueCommandCheck("SITE " + cmd);
diff --git a/ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java b/ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java
index 6ba9b9a..fac57e2 100644
--- a/ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java
+++ b/ojluni/src/main/java/sun/net/spi/DefaultProxySelector.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -33,13 +33,14 @@
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
-import java.util.StringTokenizer;
import java.io.IOException;
-import sun.misc.RegexpPool;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.StringJoiner;
+import java.util.regex.Pattern;
import sun.net.NetProperties;
import sun.net.SocksProxy;
+import static java.util.regex.Pattern.quote;
/**
* Supports proxy settings using system properties This proxy selector
@@ -87,9 +88,31 @@
private static boolean hasSystemProxies = false;
+ // Android-removed: Nonfunctional init logic: "net" library does not exist on Android.
+ /*
+ static {
+ final String key = "java.net.useSystemProxies";
+ Boolean b = AccessController.doPrivileged(
+ new PrivilegedAction<Boolean>() {
+ public Boolean run() {
+ return NetProperties.getBoolean(key);
+ }});
+ if (b != null && b.booleanValue()) {
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("net");
+ return null;
+ }
+ });
+ hasSystemProxies = init();
+ }
+ }
+ */
+
/**
* How to deal with "non proxy hosts":
- * since we do have to generate a RegexpPool we don't want to do that if
+ * since we do have to generate a pattern we don't want to do that if
* it's not necessary. Therefore we do cache the result, on a per-protocol
* basis, and change it only when the "source", i.e. the system property,
* did change.
@@ -101,17 +124,19 @@
static final String defStringVal = "localhost|127.*|[::1]|0.0.0.0|[::0]";
String hostsSource;
- RegexpPool hostsPool;
+ Pattern pattern;
final String property;
final String defaultVal;
static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
+ static NonProxyInfo socksNonProxyInfo = new NonProxyInfo("socksNonProxyHosts", null, null, defStringVal);
+ // Android-changed: Different NonProxyInfo flags for https hosts vs. http.
static NonProxyInfo httpsNonProxyInfo = new NonProxyInfo("https.nonProxyHosts", null, null, defStringVal);
- NonProxyInfo(String p, String s, RegexpPool pool, String d) {
+ NonProxyInfo(String p, String s, Pattern pattern, String d) {
property = p;
hostsSource = s;
- hostsPool = pool;
+ this.pattern = pattern;
defaultVal = d;
}
}
@@ -166,11 +191,13 @@
} else if ("https".equalsIgnoreCase(protocol)) {
// HTTPS uses the same property as HTTP, for backward
// compatibility
- //
- // Android-changed: Allow a different set of flags for https hosts.
+ // Android-changed: Different NonProxyInfo flags for https hosts vs. http.
+ // pinfo = NonProxyInfo.httpNonProxyInfo;
pinfo = NonProxyInfo.httpsNonProxyInfo;
} else if ("ftp".equalsIgnoreCase(protocol)) {
pinfo = NonProxyInfo.ftpNonProxyInfo;
+ } else if ("socket".equalsIgnoreCase(protocol)) {
+ pinfo = NonProxyInfo.socksNonProxyInfo;
}
/**
@@ -214,7 +241,20 @@
* settings (Gnome & Windows) if we were
* instructed to.
*/
- // Android-changed, hasSystemProxies is always false
+ // Android-removed: Dead code, hasSystemProxies is always false.
+ /*
+ if (hasSystemProxies) {
+ String sproto;
+ if (proto.equalsIgnoreCase("socket"))
+ sproto = "socks";
+ else
+ sproto = proto;
+ Proxy sproxy = getSystemProxy(sproto, urlhost);
+ if (sproxy != null) {
+ return sproxy;
+ }
+ }
+ */
return Proxy.NO_PROXY;
}
// If a Proxy Host is defined for that protocol
@@ -227,7 +267,7 @@
nphosts = nprop.defaultVal;
} else {
nprop.hostsSource = null;
- nprop.hostsPool = null;
+ nprop.pattern = null;
}
} else if (nphosts.length() != 0) {
// add the required default patterns
@@ -238,20 +278,11 @@
}
if (nphosts != null) {
if (!nphosts.equals(nprop.hostsSource)) {
- RegexpPool pool = new RegexpPool();
- StringTokenizer st = new StringTokenizer(nphosts, "|", false);
- try {
- while (st.hasMoreTokens()) {
- pool.add(st.nextToken().toLowerCase(), Boolean.TRUE);
- }
- } catch (sun.misc.REException ex) {
- }
- nprop.hostsPool = pool;
+ nprop.pattern = toPattern(nphosts);
nprop.hostsSource = nphosts;
}
}
- if (nprop.hostsPool != null &&
- nprop.hostsPool.match(urlhost) != null) {
+ if (shouldNotUseProxyFor(nprop.pattern, urlhost)) {
return Proxy.NO_PROXY;
}
}
@@ -324,4 +355,55 @@
return -1;
}
}
+
+ // Android-removed: Native logic not available/used on Android.
+ /*
+ private native static boolean init();
+ private synchronized native Proxy getSystemProxy(String protocol, String host);
+ */
+
+ /**
+ * @return {@code true} if given this pattern for non-proxy hosts and this
+ * urlhost the proxy should NOT be used to access this urlhost
+ */
+ static boolean shouldNotUseProxyFor(Pattern pattern, String urlhost) {
+ if (pattern == null || urlhost.isEmpty())
+ return false;
+ boolean matches = pattern.matcher(urlhost).matches();
+ return matches;
+ }
+
+ /**
+ * @param mask non-null mask
+ * @return {@link java.util.regex.Pattern} corresponding to this mask
+ * or {@code null} in case mask should not match anything
+ */
+ static Pattern toPattern(String mask) {
+ boolean disjunctionEmpty = true;
+ StringJoiner joiner = new StringJoiner("|");
+ for (String disjunct : mask.split("\\|")) {
+ if (disjunct.isEmpty())
+ continue;
+ disjunctionEmpty = false;
+ String regex = disjunctToRegex(disjunct.toLowerCase());
+ joiner.add(regex);
+ }
+ return disjunctionEmpty ? null : Pattern.compile(joiner.toString());
+ }
+
+ /**
+ * @param disjunct non-null mask disjunct
+ * @return java regex string corresponding to this mask
+ */
+ static String disjunctToRegex(String disjunct) {
+ String regex;
+ if (disjunct.startsWith("*")) {
+ regex = ".*" + quote(disjunct.substring(1));
+ } else if (disjunct.endsWith("*")) {
+ regex = quote(disjunct.substring(0, disjunct.length() - 1)) + ".*";
+ } else {
+ regex = quote(disjunct);
+ }
+ return regex;
+ }
}
diff --git a/ojluni/src/main/java/sun/net/util/IPAddressUtil.java b/ojluni/src/main/java/sun/net/util/IPAddressUtil.java
index 7ca0f12..4a58e5f 100644
--- a/ojluni/src/main/java/sun/net/util/IPAddressUtil.java
+++ b/ojluni/src/main/java/sun/net/util/IPAddressUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 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
@@ -37,89 +37,84 @@
* @param src a String representing an IPv4 address in standard format
* @return a byte array representing the IPv4 numeric address
*/
+ @SuppressWarnings("fallthrough")
public static byte[] textToNumericFormatV4(String src)
{
- if (src.length() == 0) {
+ byte[] res = new byte[INADDR4SZ];
+
+ long tmpValue = 0;
+ int currByte = 0;
+ boolean newOctet = true;
+
+ int len = src.length();
+ if (len == 0 || len > 15) {
return null;
}
-
- byte[] res = new byte[INADDR4SZ];
- String[] s = src.split("\\.", -1);
- long val;
- try {
- switch(s.length) {
- // BEGIN Android-removed
- /*
- case 1:
- // When only one part is given, the value is stored directly in
- // the network address without any byte rearrangement.
-
- val = Long.parseLong(s[0]);
- if (val < 0 || val > 0xffffffffL)
+ /*
+ * When only one part is given, the value is stored directly in
+ * the network address without any byte rearrangement.
+ *
+ * When a two part address is supplied, the last part is
+ * interpreted as a 24-bit quantity and placed in the right
+ * most three bytes of the network address. This makes the
+ * two part address format convenient for specifying Class A
+ * network addresses as net.host.
+ *
+ * When a three part address is specified, the last part is
+ * interpreted as a 16-bit quantity and placed in the right
+ * most two bytes of the network address. This makes the
+ * three part address format convenient for specifying
+ * Class B net- work addresses as 128.net.host.
+ *
+ * When four parts are specified, each is interpreted as a
+ * byte of data and assigned, from left to right, to the
+ * four bytes of an IPv4 address.
+ *
+ * We determine and parse the leading parts, if any, as single
+ * byte values in one pass directly into the resulting byte[],
+ * then the remainder is treated as a 8-to-32-bit entity and
+ * translated into the remaining bytes in the array.
+ */
+ for (int i = 0; i < len; i++) {
+ char c = src.charAt(i);
+ if (c == '.') {
+ if (newOctet || tmpValue < 0 || tmpValue > 0xff || currByte == 3) {
return null;
- res[0] = (byte) ((val >> 24) & 0xff);
- res[1] = (byte) (((val & 0xffffff) >> 16) & 0xff);
- res[2] = (byte) (((val & 0xffff) >> 8) & 0xff);
- res[3] = (byte) (val & 0xff);
- break;
- case 2:
- // When a two part address is supplied, the last part is
- // interpreted as a 24-bit quantity and placed in the right
- // most three bytes of the network address. This makes the
- // two part address format convenient for specifying Class A
- // network addresses as net.host.
-
- val = Integer.parseInt(s[0]);
- if (val < 0 || val > 0xff)
- return null;
- res[0] = (byte) (val & 0xff);
- val = Integer.parseInt(s[1]);
- if (val < 0 || val > 0xffffff)
- return null;
- res[1] = (byte) ((val >> 16) & 0xff);
- res[2] = (byte) (((val & 0xffff) >> 8) &0xff);
- res[3] = (byte) (val & 0xff);
- break;
- case 3:
- //
- // When a three part address is specified, the last part is
- // interpreted as a 16-bit quantity and placed in the right
- // most two bytes of the network address. This makes the
- // three part address format convenient for specifying
- // Class B net- work addresses as 128.net.host.
- for (int i = 0; i < 2; i++) {
- val = Integer.parseInt(s[i]);
- if (val < 0 || val > 0xff)
- return null;
- res[i] = (byte) (val & 0xff);
}
- val = Integer.parseInt(s[2]);
- if (val < 0 || val > 0xffff)
+ res[currByte++] = (byte) (tmpValue & 0xff);
+ tmpValue = 0;
+ newOctet = true;
+ } else {
+ int digit = Character.digit(c, 10);
+ if (digit < 0) {
return null;
- res[2] = (byte) ((val >> 8) & 0xff);
- res[3] = (byte) (val & 0xff);
- break;
- */
- // END Android-removed
- case 4:
- /*
- * When four parts are specified, each is interpreted as a
- * byte of data and assigned, from left to right, to the
- * four bytes of an IPv4 address.
- */
- for (int i = 0; i < 4; i++) {
- val = Integer.parseInt(s[i]);
- if (val < 0 || val > 0xff)
- return null;
- res[i] = (byte) (val & 0xff);
}
- break;
- default:
- return null;
+ tmpValue *= 10;
+ tmpValue += digit;
+ newOctet = false;
}
- } catch(NumberFormatException e) {
+ }
+ if (newOctet || tmpValue < 0 || tmpValue >= (1L << ((4 - currByte) * 8))) {
return null;
}
+ switch (currByte) {
+ // BEGIN Android-changed: Require all four parts to be given for an IPv4 address.
+ /*
+ case 0:
+ res[0] = (byte) ((tmpValue >> 24) & 0xff);
+ case 1:
+ res[1] = (byte) ((tmpValue >> 16) & 0xff);
+ case 2:
+ res[2] = (byte) ((tmpValue >> 8) & 0xff);
+ */
+ case 0:
+ case 1:
+ case 2:
+ return null;
+ // END Android-changed: Require all four parts to be given for an IPv4 address.
+ case 3:
+ res[3] = (byte) ((tmpValue >> 0) & 0xff);
+ }
return res;
}
diff --git a/ojluni/src/main/java/sun/net/util/URLUtil.java b/ojluni/src/main/java/sun/net/util/URLUtil.java
index 08c1e43..c25defb 100644
--- a/ojluni/src/main/java/sun/net/util/URLUtil.java
+++ b/ojluni/src/main/java/sun/net/util/URLUtil.java
@@ -76,5 +76,29 @@
return strForm.toString();
}
+
+ // Android-removed: Android doesn't support SecurityManager, so Permissions logic is dead code.
+ /*
+ public static Permission getConnectPermission(URL url) throws IOException {
+ String urlStringLowerCase = url.toString().toLowerCase();
+ if (urlStringLowerCase.startsWith("http:") || urlStringLowerCase.startsWith("https:")) {
+ return getURLConnectPermission(url);
+ } else if (urlStringLowerCase.startsWith("jar:http:") || urlStringLowerCase.startsWith("jar:https:")) {
+ String urlString = url.toString();
+ int bangPos = urlString.indexOf("!/");
+ urlString = urlString.substring(4, bangPos > -1 ? bangPos : urlString.length());
+ URL u = new URL(urlString);
+ return getURLConnectPermission(u);
+ // If protocol is HTTP or HTTPS than use URLPermission object
+ } else {
+ return url.openConnection().getPermission();
+ }
+ }
+
+ private static Permission getURLConnectPermission(URL url) {
+ String urlString = url.getProtocol() + "://" + url.getAuthority() + url.getPath();
+ return new URLPermission(urlString);
+ }
+ */
}
diff --git a/ojluni/src/main/java/sun/net/www/MessageHeader.java b/ojluni/src/main/java/sun/net/www/MessageHeader.java
index 0237a85..34b6307 100644
--- a/ojluni/src/main/java/sun/net/www/MessageHeader.java
+++ b/ojluni/src/main/java/sun/net/www/MessageHeader.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -31,13 +31,7 @@
import java.io.*;
import java.util.Collections;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
+import java.util.*;
/** An RFC 844 or MIME message header. Includes methods
for parsing headers from incoming streams, fetching
@@ -61,6 +55,17 @@
}
/**
+ * Returns list of header names in a comma separated list
+ */
+ public synchronized String getHeaderNamesInList() {
+ StringJoiner joiner = new StringJoiner(",");
+ for (int i=0; i<nkeys; i++) {
+ joiner.add(keys[i]);
+ }
+ return joiner.toString();
+ }
+
+ /**
* Reset a message header (all key/values removed)
*/
public synchronized void reset() {
@@ -148,7 +153,7 @@
for (int i=0; i<nkeys; i++) {
if (k.equalsIgnoreCase(keys[i])
&& values[i] != null && values[i].length() > 5
- && values[i].regionMatches(true, 0, "NTLM ", 0, 5)) {
+ && values[i].substring(0, 5).equalsIgnoreCase("NTLM ")) {
found = true;
break;
}
@@ -236,7 +241,8 @@
return filterAndAddHeaders(excludeList, null);
}
- public synchronized Map<String, List<String>> filterAndAddHeaders(String[] excludeList, Map<String, List<String>> include) {
+ public synchronized Map<String, List<String>> filterAndAddHeaders(
+ String[] excludeList, Map<String, List<String>> include) {
boolean skipIt = false;
Map<String, List<String>> m = new HashMap<String, List<String>>();
for (int i = nkeys; --i >= 0;) {
@@ -265,15 +271,13 @@
}
if (include != null) {
- Iterator entries = include.entrySet().iterator();
- while (entries.hasNext()) {
- Map.Entry entry = (Map.Entry)entries.next();
- List l = (List)m.get(entry.getKey());
+ for (Map.Entry<String,List<String>> entry: include.entrySet()) {
+ List<String> l = m.get(entry.getKey());
if (l == null) {
- l = new ArrayList();
- m.put((String)entry.getKey(), l);
+ l = new ArrayList<String>();
+ m.put(entry.getKey(), l);
}
- l.add(entry.getValue());
+ l.addAll(entry.getValue());
}
}
@@ -437,6 +441,7 @@
}
/** Parse and merge a MIME header from an input stream. */
+ @SuppressWarnings("fallthrough")
public void mergeHeader(InputStream is) throws java.io.IOException {
if (is == null)
return;
@@ -458,6 +463,7 @@
break;
case '\t':
c = ' ';
+ /*fall through*/
case ' ':
inKey = false;
break;
diff --git a/ojluni/src/main/java/sun/net/www/MeteredStream.java b/ojluni/src/main/java/sun/net/www/MeteredStream.java
index 17c8b83..26fe85d 100644
--- a/ojluni/src/main/java/sun/net/www/MeteredStream.java
+++ b/ojluni/src/main/java/sun/net/www/MeteredStream.java
@@ -142,15 +142,17 @@
return 0;
}
-// Android-changed: Remove support for Android-removed class ChunkedInputSTream
-// if (in instanceof ChunkedInputStream) {
-// n = in.skip(n);
-// }
-// else {
+ // Android-removed: Removed support for Android-removed class ChunkedInputStream.
+ /*
+ if (in instanceof ChunkedInputStream) {
+ n = in.skip(n);
+ }
+ else {
+ */
// just skip min(n, num_bytes_left)
long min = (n > expected - count) ? expected - count: n;
n = in.skip(min);
-// }
+ // }
justRead(n);
return n;
}
diff --git a/ojluni/src/main/java/sun/net/www/URLConnection.java b/ojluni/src/main/java/sun/net/www/URLConnection.java
index 2760acc..c495928 100644
--- a/ojluni/src/main/java/sun/net/www/URLConnection.java
+++ b/ojluni/src/main/java/sun/net/www/URLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1995, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -26,12 +26,7 @@
package sun.net.www;
import java.net.URL;
-import java.net.ContentHandler;
import java.util.*;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.BufferedInputStream;
-import java.net.UnknownServiceException;
/**
* A class to represent an active connection to an object
@@ -99,7 +94,7 @@
public Map<String,List<String>> getRequestProperties() {
if (connected)
throw new IllegalStateException("Already connected");
- return Collections.EMPTY_MAP;
+ return Collections.emptyMap();
}
public String getHeaderField(String name) {
diff --git a/ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java
index 24f2f3b..e9f3d78 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/ftp/FtpURLConnection.java
@@ -81,10 +81,12 @@
*/
public class FtpURLConnection extends URLConnection {
-// Android-changed: Removed support for proxying FTP over HTTP since it
-// relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
-// // In case we have to use proxies, we use HttpURLConnection
-// HttpURLConnection http = null;
+ // Android-changed: Removed support for proxying FTP over HTTP.
+ // It relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ /*
+ // In case we have to use proxies, we use HttpURLConnection
+ HttpURLConnection http = null;
+ */
private Proxy instProxy;
InputStream is = null;
@@ -163,6 +165,8 @@
*
* @param url The <code>URL</code> to retrieve or store.
*/
+ // Android-changed: Ctors can throw IOException for NetworkSecurityPolicy enforcement.
+ // public FtpURLConnection(URL url) {
public FtpURLConnection(URL url) throws IOException {
this(url, null);
}
@@ -170,19 +174,22 @@
/**
* Same as FtpURLconnection(URL) with a per connection proxy specified
*/
+ // Android-changed: Ctors can throw IOException for NetworkSecurityPolicy enforcement.
+ // FtpURLConnection(URL url, Proxy p) {
FtpURLConnection(URL url, Proxy p) throws IOException {
super(url);
instProxy = p;
host = url.getHost();
port = url.getPort();
String userInfo = url.getUserInfo();
-
+ // BEGIN Android-added: Enforce NetworkSecurityPolicy.isClearTextTrafficPermitted().
if (!NetworkSecurityPolicy.getInstance().isCleartextTrafficPermitted()) {
// Cleartext network traffic is not permitted -- refuse this connection.
throw new IOException("Cleartext traffic not permitted: "
+ url.getProtocol() + "://" + host
+ ((url.getPort() >= 0) ? (":" + url.getPort()) : ""));
}
+ // END Android-added: Enforce NetworkSecurityPolicy.isClearTextTrafficPermitted().
if (userInfo != null) { // get the user and password
int delimiter = userInfo.indexOf(':');
@@ -246,50 +253,56 @@
continue;
}
// OK, we have an http proxy
- // Android-changed: Removed support for proxying FTP over HTTP since it
- // relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ // BEGIN Android-changed: Removed support for proxying FTP over HTTP.
+ // It relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ /*
+ InetSocketAddress paddr = (InetSocketAddress) p.address();
+ try {
+ http = new HttpURLConnection(url, p);
+ http.setDoInput(getDoInput());
+ http.setDoOutput(getDoOutput());
+ if (connectTimeout >= 0) {
+ http.setConnectTimeout(connectTimeout);
+ }
+ if (readTimeout >= 0) {
+ http.setReadTimeout(readTimeout);
+ }
+ http.connect();
+ connected = true;
+ return;
+ } catch (IOException ioe) {
+ sel.connectFailed(uri, paddr, ioe);
+ http = null;
+ }
+ */
sel.connectFailed(uri, p.address(), new IOException("FTP connections over HTTP proxy not supported"));
continue;
-// InetSocketAddress paddr = (InetSocketAddress) p.address();
-// try {
-// http = new HttpURLConnection(url, p);
-// http.setDoInput(getDoInput());
-// http.setDoOutput(getDoOutput());
-// if (connectTimeout >= 0) {
-// http.setConnectTimeout(connectTimeout);
-// }
-// if (readTimeout >= 0) {
-// http.setReadTimeout(readTimeout);
-// }
-// http.connect();
-// connected = true;
-// return;
-// } catch (IOException ioe) {
-// sel.connectFailed(uri, paddr, ioe);
-// http = null;
-// }
+ // END Android-changed: Removed support for proxying FTP over HTTP.
}
}
} else { // per connection proxy specified
p = instProxy;
-// Android-changed: Removed support for proxying FTP over HTTP since it
-// relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
-// As specified in the documentation for URL.openConnection(Proxy), we
-// ignore the unsupported proxy and attempt a normal (direct) connection
-// if (p.type() == Proxy.Type.HTTP) {
-// http = new HttpURLConnection(url, instProxy);
-// http.setDoInput(getDoInput());
-// http.setDoOutput(getDoOutput());
-// if (connectTimeout >= 0) {
-// http.setConnectTimeout(connectTimeout);
-// }
-// if (readTimeout >= 0) {
-// http.setReadTimeout(readTimeout);
-// }
-// http.connect();
-// connected = true;
-// return;
-// }
+ // BEGIN Android-changed: Removed support for proxying FTP over HTTP.
+ // It relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ // As specified in the documentation for URL.openConnection(Proxy), we
+ // ignore the unsupported proxy and attempt a normal (direct) connection
+ /*
+ if (p.type() == Proxy.Type.HTTP) {
+ http = new HttpURLConnection(url, instProxy);
+ http.setDoInput(getDoInput());
+ http.setDoOutput(getDoOutput());
+ if (connectTimeout >= 0) {
+ http.setConnectTimeout(connectTimeout);
+ }
+ if (readTimeout >= 0) {
+ http.setReadTimeout(readTimeout);
+ }
+ http.connect();
+ connected = true;
+ return;
+ }
+ */
+ // END Android-changed: Removed support for proxying FTP over HTTP.
}
if (user == null) {
@@ -319,7 +332,7 @@
throw new IOException(fe);
}
try {
- ftp.login(user, password.toCharArray());
+ ftp.login(user, password == null ? null : password.toCharArray());
} catch (sun.net.ftp.FtpProtocolException e) {
ftp.close();
// Backward compatibility
@@ -410,11 +423,14 @@
if (!connected) {
connect();
}
- // Android-changed: Removed support for proxying FTP over HTTP since it
- // relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
-// if (http != null) {
-// return http.getInputStream();
-// }
+
+ // Android-changed: Removed support for proxying FTP over HTTP.
+ // It relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ /*
+ if (http != null) {
+ return http.getInputStream();
+ }
+ */
if (os != null) {
throw new IOException("Already opened for output");
@@ -525,15 +541,18 @@
if (!connected) {
connect();
}
-// Android-changed: Removed support for proxying FTP over HTTP since it
-// relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
-// if (http != null) {
-// OutputStream out = http.getOutputStream();
-// // getInputStream() is neccessary to force a writeRequests()
-// // on the http client.
-// http.getInputStream();
-// return out;
-// }
+
+ // Android-changed: Removed support for proxying FTP over HTTP.
+ // It relies on the removed sun.net.www.protocol.http.HttpURLConnection API.
+ /*
+ if (http != null) {
+ OutputStream out = http.getOutputStream();
+ // getInputStream() is neccessary to force a writeRequests()
+ // on the http client.
+ http.getInputStream();
+ return out;
+ }
+ */
if (is != null) {
throw new IOException("Already opened for input");
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java b/ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java
index 62686c6..8e9f8e3 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/jar/Handler.java
@@ -123,6 +123,7 @@
@Override
+ @SuppressWarnings("deprecation")
protected void parseURL(URL url, String spec,
int start, int limit) {
String file = null;
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java b/ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java
index ae86964..edd99ff 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/jar/JarFileFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
diff --git a/ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java b/ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java
index 4c5dc87..d7c4424 100644
--- a/ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java
+++ b/ojluni/src/main/java/sun/net/www/protocol/jar/JarURLConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -125,7 +125,9 @@
* to get the jarFile, and set it as our permission.
*/
if (getUseCaches()) {
+ boolean oldUseCaches = jarFileURLConnection.getUseCaches();
jarFileURLConnection = factory.getConnection(jarFile);
+ jarFileURLConnection.setUseCaches(oldUseCaches);
}
if ((entryName != null)) {
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/IOUtil.java b/ojluni/src/main/java/sun/nio/ch/IOUtil.java
index 86dab9f..6988b86 100644
--- a/ojluni/src/main/java/sun/nio/ch/IOUtil.java
+++ b/ojluni/src/main/java/sun/nio/ch/IOUtil.java
@@ -345,7 +345,31 @@
static native int iovMax();
+ // Android-removed: Code to load native libraries, doesn't make sense on Android.
+ /*
+ static native void initIDs();
+
+ /**
+ * Used to trigger loading of native libraries
+ *
+ public static void load() { }
+ */
+
static {
+ // Android-removed: Code to load native libraries, doesn't make sense on Android.
+ /*
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("net");
+ System.loadLibrary("nio");
+ return null;
+ }
+ });
+
+ initIDs();
+ */
+
IOV_MAX = iovMax();
}
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/reflect/CallerSensitive.java b/ojluni/src/main/java/sun/reflect/CallerSensitive.java
index 79fbdfc..0c78da0 100644
--- a/ojluni/src/main/java/sun/reflect/CallerSensitive.java
+++ b/ojluni/src/main/java/sun/reflect/CallerSensitive.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
diff --git a/ojluni/src/main/java/sun/reflect/Reflection.java b/ojluni/src/main/java/sun/reflect/Reflection.java
index a3fa56d..bb82b43 100644
--- a/ojluni/src/main/java/sun/reflect/Reflection.java
+++ b/ojluni/src/main/java/sun/reflect/Reflection.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -35,8 +35,10 @@
public class Reflection {
- public static void ensureMemberAccess(Class currentClass,
- Class memberClass,
+ // Android-removed: Dead code: Misc unused fields and methods.
+
+ public static void ensureMemberAccess(Class<?> currentClass,
+ Class<?> memberClass,
Object target,
int modifiers)
throws IllegalAccessException
@@ -55,13 +57,13 @@
}
}
- public static boolean verifyMemberAccess(Class currentClass,
+ public static boolean verifyMemberAccess(Class<?> currentClass,
// Declaring class of field
// or method
- Class memberClass,
+ Class<?> memberClass,
// May be NULL in case of statics
- Object target,
- int modifiers)
+ Object target,
+ int modifiers)
{
// Verify that currentClass can access a field, method, or
// constructor of memberClass, where that member's access bits are
@@ -118,7 +120,7 @@
if (Modifier.isProtected(modifiers)) {
// Additional test for protected members: JLS 6.6.2
- Class targetClass = (target == null ? memberClass : target.getClass());
+ Class<?> targetClass = (target == null ? memberClass : target.getClass());
if (targetClass != currentClass) {
if (!gotIsSameClassPackage) {
isSameClassPackage = isSameClassPackage(currentClass, memberClass);
@@ -135,7 +137,7 @@
return true;
}
- private static boolean isSameClassPackage(Class c1, Class c2) {
+ private static boolean isSameClassPackage(Class<?> c1, Class<?> c2) {
return isSameClassPackage(c1.getClassLoader(), c1.getName(),
c2.getClassLoader(), c2.getName());
}
@@ -190,8 +192,8 @@
}
}
- static boolean isSubclassOf(Class queryClass,
- Class ofClass)
+ static boolean isSubclassOf(Class<?> queryClass,
+ Class<?> ofClass)
{
while (queryClass != null) {
if (queryClass == ofClass) {
@@ -201,4 +203,7 @@
}
return false;
}
+
+ // Android-removed: Dead code: Misc unused methods.
+
}
diff --git a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
index f9c2928..5896f15 100644
--- a/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
+++ b/ojluni/src/main/java/sun/reflect/misc/ReflectUtil.java
@@ -33,20 +33,22 @@
private ReflectUtil() {
}
- public static Class forName(String name)
+ public static Class<?> forName(String name)
throws ClassNotFoundException {
checkPackageAccess(name);
return Class.forName(name);
}
- public static Object newInstance(Class cls)
+ public static Object newInstance(Class<?> cls)
throws InstantiationException, IllegalAccessException {
checkPackageAccess(cls);
return cls.newInstance();
}
- private static boolean isSubclassOf(Class queryClass,
- Class ofClass)
+ // Android-removed: Dead code: Unused method ensureMemberAccess()
+
+ private static boolean isSubclassOf(Class<?> queryClass,
+ Class<?> ofClass)
{
while (queryClass != null) {
if (queryClass == ofClass) {
@@ -57,6 +59,8 @@
return false;
}
+ // Android-removed: Dead code: Unused method conservativeCheckMemberAccess()
+
/**
* Checks package access on the given class.
*
@@ -94,7 +98,7 @@
}
}
- public static boolean isPackageAccessible(Class clazz) {
+ public static boolean isPackageAccessible(Class<?> clazz) {
try {
checkPackageAccess(clazz);
} catch (SecurityException e) {
@@ -177,6 +181,13 @@
}
}
+ // Android-changed: Proxy classes are generated in the default package on Android.
+ /*
+ // Note that bytecode instrumentation tools may exclude 'sun.*'
+ // classes but not generated proxy classes and so keep it in com.sun.*
+ public static final String PROXY_PACKAGE = "com.sun.proxy";
+ */
+
/**
* Test if the given class is a proxy class that implements
* non-public interface. Such proxy class may be in a non-restricted
@@ -186,10 +197,14 @@
String name = cls.getName();
int i = name.lastIndexOf('.');
String pkg = (i != -1) ? name.substring(0, i) : "";
-
- // NOTE: Android creates proxies in the "default" package (and not com.sun.proxy), which
- // makes this check imprecise. However, this function is only ever called if there's
- // a security manager installed (which is the never case on android).
+ // Android-changed: Proxy classes are generated in the default package on Android.
+ // The use of the default package (as opposed to com.sun.proxy) makes this check
+ // imprecise. However, this function is only ever called if there's
+ // a security manager installed (which is the never case on Android).
+ // return Proxy.isProxyClass(cls) && !pkg.equals(PROXY_PACKAGE);
return Proxy.isProxyClass(cls) && !pkg.isEmpty();
}
+
+ // Android-removed: Dead code: unused method checkProxyMethod()
+ // Android-removed: Dead code: unused method isVMAnonymousClass()
}
diff --git a/ojluni/src/main/java/sun/security/jca/JCAUtil.java b/ojluni/src/main/java/sun/security/jca/JCAUtil.java
index b7bae41..fde9be5 100644
--- a/ojluni/src/main/java/sun/security/jca/JCAUtil.java
+++ b/ojluni/src/main/java/sun/security/jca/JCAUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 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
@@ -41,12 +41,6 @@
// no instantiation
}
- // lock to use for synchronization
- private static final Object LOCK = JCAUtil.class;
-
- // cached SecureRandom instance
- private static volatile SecureRandom secureRandom;
-
// size of the temporary arrays we use. Should fit into the CPU's 1st
// level cache and could be adjusted based on the platform
private final static int ARRAY_SIZE = 4096;
@@ -60,26 +54,19 @@
return Math.min(ARRAY_SIZE, totalSize);
}
+ // cached SecureRandom instance
+ private static class CachedSecureRandomHolder {
+ public static SecureRandom instance = new SecureRandom();
+ }
+
/**
- * Get a SecureRandom instance. This method should me used by JDK
+ * Get a SecureRandom instance. This method should be used by JDK
* internal code in favor of calling "new SecureRandom()". That needs to
* iterate through the provider table to find the default SecureRandom
* implementation, which is fairly inefficient.
*/
public static SecureRandom getSecureRandom() {
- // we use double checked locking to minimize synchronization
- // works because we use a volatile reference
- SecureRandom r = secureRandom;
- if (r == null) {
- synchronized (LOCK) {
- r = secureRandom;
- if (r == null) {
- r = new SecureRandom();
- secureRandom = r;
- }
- }
- }
- return r;
+ return CachedSecureRandomHolder.instance;
}
}
diff --git a/ojluni/src/main/java/sun/security/jca/ProviderConfig.java b/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
index fc4ee76..2acf30d 100644
--- a/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
+++ b/ojluni/src/main/java/sun/security/jca/ProviderConfig.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -209,6 +209,7 @@
debug.println("Loading provider: " + ProviderConfig.this);
}
+// BEGIN Android-changed: Prefer the boot classloader to the system classloader.
try {
// First try with the boot classloader.
return initProvider(className, Object.class.getClassLoader());
@@ -269,6 +270,7 @@
return null;
}
}
+// END Android-changed: Prefer the boot classloader to the system classloader.
/**
* Perform property expansion of the provider value.
diff --git a/ojluni/src/main/java/sun/security/jca/ProviderList.java b/ojluni/src/main/java/sun/security/jca/ProviderList.java
index d9b04c6..66c8262 100644
--- a/ojluni/src/main/java/sun/security/jca/ProviderList.java
+++ b/ojluni/src/main/java/sun/security/jca/ProviderList.java
@@ -69,13 +69,7 @@
// used to avoid explicit null checks in various places
private static final Provider EMPTY_PROVIDER =
new Provider("##Empty##", 1.0d, "initialization in progress") {
- // BEGIN Android-added
- // TODO(33172161): the computation of the default in Android yields
- // -2591074641286775682L . Check why there's a difference and possibly change number
- // accordingly.
- // END Android-added
private static final long serialVersionUID = 1151354171352296389L;
- // END Android-changed
// override getService() to return null slightly faster
public Service getService(String type, String algorithm) {
return null;
diff --git a/ojluni/src/main/java/sun/security/jca/Providers.java b/ojluni/src/main/java/sun/security/jca/Providers.java
index ddcf505..e39543a 100644
--- a/ojluni/src/main/java/sun/security/jca/Providers.java
+++ b/ojluni/src/main/java/sun/security/jca/Providers.java
@@ -54,6 +54,7 @@
providerList = ProviderList.EMPTY;
providerList = ProviderList.fromSecurityProperties();
+ // BEGIN Android-added: Initialize all providers and assert that this succeeds.
// removeInvalid is specified to try initializing all configured providers
// and removing those that aren't instantiable. This has the side effect
// of eagerly initializing all providers.
@@ -62,6 +63,7 @@
if (numConfiguredProviders != providerList.size()) {
throw new AssertionError("Unable to configure default providers");
}
+ // END Android-added: Initialize all providers and assert that this succeeds.
}
private Providers() {
@@ -91,7 +93,7 @@
// Hardcoded classnames of providers to use for JAR verification.
// MUST NOT be on the bootclasspath and not in signed JAR files.
private static final String[] jarVerificationProviders = {
- // BEGIN Android-changed
+ // BEGIN Android-changed: Use Conscrypt and BC, not the sun.security providers.
/*
"sun.security.provider.Sun",
"sun.security.rsa.SunRsaSign",
@@ -102,7 +104,7 @@
"com.android.org.conscrypt.OpenSSLProvider",
"com.android.org.bouncycastle.jce.provider.BouncyCastleProvider",
"com.android.org.conscrypt.JSSEProvider",
- // END Android-changed
+ // END Android-changed: Use Conscrypt and BC, not the sun.security providers.
BACKUP_PROVIDER_CLASSNAME,
};
diff --git a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
index 49d898a..f28bea7 100644
--- a/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
+++ b/ojluni/src/main/java/sun/security/pkcs/PKCS7.java
@@ -1026,7 +1026,8 @@
byte[] content,
String signatureAlgorithm,
URI tsaURI,
- String tSAPolicyID)
+ String tSAPolicyID,
+ String tSADigestAlg)
throws CertificateException, IOException, NoSuchAlgorithmException
{
@@ -1035,7 +1036,8 @@
if (tsaURI != null) {
// Timestamp the signature
HttpTimestamper tsa = new HttpTimestamper(tsaURI);
- byte[] tsToken = generateTimestampToken(tsa, tSAPolicyID, signature);
+ byte[] tsToken = generateTimestampToken(
+ tsa, tSAPolicyID, tSADigestAlg, signature);
// Insert the timestamp token into the PKCS #7 signer info element
// (as an unsigned attribute)
@@ -1093,6 +1095,7 @@
*
private static byte[] generateTimestampToken(Timestamper tsa,
String tSAPolicyID,
+ String tSADigestAlg,
byte[] toBeTimestamped)
throws IOException, CertificateException
{
@@ -1100,11 +1103,10 @@
MessageDigest messageDigest = null;
TSRequest tsQuery = null;
try {
- // SHA-1 is always used.
- messageDigest = MessageDigest.getInstance("SHA-1");
+ messageDigest = MessageDigest.getInstance(tSADigestAlg);
tsQuery = new TSRequest(tSAPolicyID, toBeTimestamped, messageDigest);
} catch (NoSuchAlgorithmException e) {
- // ignore
+ throw new IllegalArgumentException(e);
}
// Generate a nonce
@@ -1132,9 +1134,13 @@
PKCS7 tsToken = tsReply.getToken();
TimestampToken tst = tsReply.getTimestampToken();
- if (!tst.getHashAlgorithm().getName().equals("SHA-1")) {
- throw new IOException("Digest algorithm not SHA-1 in "
- + "timestamp token");
+ try {
+ if (!tst.getHashAlgorithm().equals(AlgorithmId.get(tSADigestAlg))) {
+ throw new IOException("Digest algorithm not " + tSADigestAlg + " in "
+ + "timestamp token");
+ }
+ } catch (NoSuchAlgorithmException nase) {
+ throw new IllegalArgumentException(); // should have been caught before
}
if (!MessageDigest.isEqual(tst.getHashedMessage(),
tsQuery.getHashedMessage())) {
@@ -1172,5 +1178,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 e2f8e28..ef65da9 100644
--- a/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
+++ b/ojluni/src/main/java/sun/security/pkcs/SignerInfo.java
@@ -60,6 +60,7 @@
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.util.DisabledAlgorithmConstraints;
+import sun.security.util.KeyUtil;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
@@ -424,7 +425,9 @@
// 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());
+ "Disabled key used: " +
+ KeyUtil.getKeySize(key) + " bit " +
+ key.getAlgorithm());
}
if (cert.hasUnsupportedCriticalExtension()) {
@@ -530,6 +533,23 @@
return unauthenticatedAttributes;
}
+ /**
+ * Returns the timestamp PKCS7 data unverified.
+ * @return a PKCS7 object
+ */
+ public PKCS7 getTsToken() throws IOException {
+ if (unauthenticatedAttributes == null) {
+ return null;
+ }
+ PKCS9Attribute tsTokenAttr =
+ unauthenticatedAttributes.getAttribute(
+ PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
+ if (tsTokenAttr == null) {
+ return null;
+ }
+ return new PKCS7((byte[])tsTokenAttr.getValue());
+ }
+
/*
* Extracts a timestamp from a PKCS7 SignerInfo.
*
@@ -558,19 +578,12 @@
if (timestamp != null || !hasTimestamp)
return timestamp;
- if (unauthenticatedAttributes == null) {
- hasTimestamp = false;
- return null;
- }
- PKCS9Attribute tsTokenAttr =
- unauthenticatedAttributes.getAttribute(
- PKCS9Attribute.SIGNATURE_TIMESTAMP_TOKEN_OID);
- if (tsTokenAttr == null) {
+ PKCS7 tsToken = getTsToken();
+ if (tsToken == null) {
hasTimestamp = false;
return null;
}
- PKCS7 tsToken = new PKCS7((byte[])tsTokenAttr.getValue());
// Extract the content (an encoded timestamp token info)
byte[] encTsTokenInfo = tsToken.getContentInfo().getData();
// Extract the signer (the Timestamping Authority)
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 4e0c3b6..d2d9e36 100644
--- a/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java
+++ b/ojluni/src/main/java/sun/security/provider/certpath/PKIXCertPathValidator.java
@@ -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.
diff --git a/ojluni/src/main/java/sun/security/util/Debug.java b/ojluni/src/main/java/sun/security/util/Debug.java
index 6ddb08d..ff5a879 100644
--- a/ojluni/src/main/java/sun/security/util/Debug.java
+++ b/ojluni/src/main/java/sun/security/util/Debug.java
@@ -26,9 +26,9 @@
package sun.security.util;
import java.math.BigInteger;
-import java.util.Locale;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Locale;
/**
* A utility class for debuging.
@@ -37,15 +37,39 @@
*/
public class Debug {
- private static final String args = null;
+ private String prefix;
- private final String prefix;
+ private static String args;
- private Debug(String prefix) {
- this.prefix = prefix;
+ // BEGIN Android-changed: Debug is stubbed and disabled on Android.
+ // Removing the static initializer removes the only pathway to set args, which
+ // in turn means that isOn() always returns false and so no code in this
+ // class does anything.
+ /*
+ static {
+ args = java.security.AccessController.doPrivileged
+ (new sun.security.action.GetPropertyAction
+ ("java.security.debug"));
+
+ String args2 = java.security.AccessController.doPrivileged
+ (new sun.security.action.GetPropertyAction
+ ("java.security.auth.debug"));
+
+ if (args == null) {
+ args = args2;
+ } else {
+ if (args2 != null)
+ args = args + "," + args2;
+ }
+
+ if (args != null) {
+ args = marshal(args);
+ if (args.equals("help")) {
+ Help();
+ }
+ }
}
- /*
From public static void Help() : Serves as a documentation of the
values that "args" accepts.
@@ -99,6 +123,7 @@
System.err.println("Note: Separate multiple options with a comma");
System.exit(0);
*/
+ // END Android-changed: Debug is stubbed and disabled on Android.
/**
* Get a Debug object corresponding to whether or not the given
@@ -117,7 +142,8 @@
public static Debug getInstance(String option, String prefix)
{
if (isOn(option)) {
- Debug d = new Debug(prefix);
+ Debug d = new Debug();
+ d.prefix = prefix;
return d;
} else {
return null;
@@ -159,6 +185,16 @@
System.err.println(prefix + ":");
}
+ // Android-removed: Nothing uses this code and it serves no purpose.
+ /**
+ * print a message to stderr that is prefixed with the prefix.
+ *
+
+ public static void println(String prefix, String message)
+ {
+ System.err.println(prefix + ": "+message);
+ }
+ */
/**
* return a hexadecimal printed representation of the specified
diff --git a/ojluni/src/main/java/sun/security/util/DerInputStream.java b/ojluni/src/main/java/sun/security/util/DerInputStream.java
index b182d4e..6608676 100644
--- a/ojluni/src/main/java/sun/security/util/DerInputStream.java
+++ b/ojluni/src/main/java/sun/security/util/DerInputStream.java
@@ -325,6 +325,7 @@
* (used to initialize an auto-growing data structure)
* @return array of the values in the sequence
*/
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
public DerValue[] getSequence(int startLen,
boolean originalEncodedFormRetained) throws IOException {
tag = (byte)buffer.read();
@@ -347,6 +348,7 @@
return getSequence(
startLen,
false); // no need to retain original encoded form
+ // END Android-changed: Original encoded form needed for APKs parsing/validation
}
/**
@@ -379,6 +381,7 @@
*/
public DerValue[] getSet(int startLen, boolean implicit)
throws IOException {
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
return getSet(
startLen,
implicit,
@@ -395,6 +398,7 @@
}
}
return (readVector(startLen, originalEncodedFormRetained));
+ // END Android-changed: Original encoded form needed for APKs parsing/validation
}
/*
@@ -403,6 +407,7 @@
* this same helper routine.
*/
protected DerValue[] readVector(int startLen) throws IOException {
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
return readVector(
startLen,
false); // no need to retain original encoded form
@@ -415,6 +420,7 @@
*/
protected DerValue[] readVector(int startLen,
boolean originalEncodedFormRetained) throws IOException {
+ // END Android-changed: Original encoded form needed for APKs parsing/validation
DerInputStream newstr;
byte lenByte = (byte)buffer.read();
@@ -459,6 +465,7 @@
DerValue value;
do {
+ // Android-changed: Original encoded form needed for APKs parsing/validation
value = new DerValue(newstr.buffer, originalEncodedFormRetained);
vec.addElement(value);
} while (newstr.available() > 0);
diff --git a/ojluni/src/main/java/sun/security/util/DerValue.java b/ojluni/src/main/java/sun/security/util/DerValue.java
index 21116dc..3045995 100644
--- a/ojluni/src/main/java/sun/security/util/DerValue.java
+++ b/ojluni/src/main/java/sun/security/util/DerValue.java
@@ -72,11 +72,13 @@
private int length;
+ // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
/**
* The original encoded form of the whole value (tag, length, and value)
* or null if the form was not provided or was not retained during parsing.
*/
private byte[] originalEncodedForm;
+ // END Android-added: Original encoded form needed for APKs parsing/validation
/*
* The type starts at the first byte of the encoding, and
@@ -249,6 +251,7 @@
/*
* package private
*/
+ // BEGIN Android-changed: Original encoded form needed for APKs parsing/validation
DerValue(DerInputBuffer in, boolean originalEncodedFormRetained)
throws IOException {
// XXX must also parse BER-encoded constructed
@@ -294,6 +297,7 @@
int consumed = in.getPos() - startPosInInput;
originalEncodedForm = in.getSlice(startPosInInput, consumed);
}
+ // END Android-changed: Original encoded form needed for APKs parsing/validation
}
/**
@@ -834,6 +838,7 @@
}
}
+ // BEGIN Android-added: Original encoded form needed for APKs parsing/validation
/**
* Returns the original encoded form or {@code null} if the form was not
* retained or is not available.
@@ -842,6 +847,7 @@
return (originalEncodedForm != null)
? originalEncodedForm.clone() : null;
}
+ // END Android-added: Original encoded form needed for APKs parsing/validation
/**
* Returns a DER-encoded value, such that if it's passed to the
diff --git a/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java b/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
index aecb341..a46b318 100644
--- a/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
+++ b/ojluni/src/main/java/sun/security/util/DisabledAlgorithmConstraints.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -95,6 +95,7 @@
@Override
final public boolean permits(Set<CryptoPrimitive> primitives,
String algorithm, AlgorithmParameters parameters) {
+
if (primitives == null || primitives.isEmpty()) {
throw new IllegalArgumentException(
"No cryptographic primitive specified");
@@ -297,6 +298,7 @@
c = new jdkCAConstraint(algorithm);
jdkCALimit = true;
}
+
// Link multiple conditions for a single constraint
// into a linked list.
if (lastConstraint == null) {
diff --git a/ojluni/src/main/java/sun/security/util/KeyUtil.java b/ojluni/src/main/java/sun/security/util/KeyUtil.java
index e3efcff..c12a4ce 100644
--- a/ojluni/src/main/java/sun/security/util/KeyUtil.java
+++ b/ojluni/src/main/java/sun/security/util/KeyUtil.java
@@ -1,6 +1,6 @@
/*
* Copyright 2016 The Android Open Source Project
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012,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
@@ -91,18 +91,8 @@
// END Android-changed
} else if (key instanceof DSAKey) {
DSAKey pubk = (DSAKey)key;
- // BEGIN Android-changed
- // Was: size = pubk.getParams().getP().bitLength();
- DSAParams params = pubk.getParams();
- // According to RFC 3279 section 2.3.2, DSA keys are allowed
- // to inherit parameters in an X.509 certificate issuer's
- // key parameters, so the parameters may be null. The parent
- // key will be rejected if its parameters don't pass, so this
- // is okay.
- if (params != null) {
- size = params.getP().bitLength();
- }
- // END Android-changed
+ DSAParams params = pubk.getParams(); // params can be null
+ size = (params != null) ? params.getP().bitLength() : -1;
} else if (key instanceof DHKey) {
DHKey pubk = (DHKey)key;
size = pubk.getParams().getP().bitLength();
@@ -163,8 +153,6 @@
/**
* Returns whether the specified provider is Oracle provider or not.
- * <P>
- * Note that this method is only apply to SunJCE and SunPKCS11 at present.
*
* @param providerName
* the provider name
@@ -172,8 +160,11 @@
* {@code providerName} is Oracle provider
*
public static final boolean isOracleJCEProvider(String providerName) {
- return providerName != null && (providerName.equals("SunJCE") ||
- providerName.startsWith("SunPKCS11"));
+ return providerName != null &&
+ (providerName.equals("SunJCE") ||
+ providerName.equals("SunMSCAPI") ||
+ providerName.equals("OracleUcrypto") ||
+ providerName.startsWith("SunPKCS11"));
}
/**
@@ -218,7 +209,7 @@
byte[] encoded, boolean isFailOver) {
if (random == null) {
- random = new SecureRandom();
+ random = JCAUtil.getSecureRandom();
}
byte[] replacer = new byte[48];
random.nextBytes(replacer);
@@ -322,5 +313,5 @@
}
*/
// END Android-removed
-}
+}
diff --git a/ojluni/src/main/java/sun/security/util/ObjectIdentifier.java b/ojluni/src/main/java/sun/security/util/ObjectIdentifier.java
index 38d171a..58f26c3 100644
--- a/ojluni/src/main/java/sun/security/util/ObjectIdentifier.java
+++ b/ojluni/src/main/java/sun/security/util/ObjectIdentifier.java
@@ -255,7 +255,13 @@
+ " (tag = " + type_id + ")"
);
- encoding = new byte[in.getLength()];
+ int len = in.getLength();
+ if (len > in.available()) {
+ throw new IOException("ObjectIdentifier() -- length exceeds" +
+ "data available. Length: " + len + ", Available: " +
+ in.available());
+ }
+ encoding = new byte[len];
in.getBytes(encoding);
check(encoding);
}
@@ -354,6 +360,7 @@
* @return components in an int array, if all the components are less than
* Integer.MAX_VALUE. Otherwise, null.
*/
+ // Android-changed: s/private/public: Needed to keep sort order of RDN from prev impl
public int[] toIntArray() {
int length = encoding.length;
int[] result = new int[20];
diff --git a/ojluni/src/main/java/sun/security/x509/AVA.java b/ojluni/src/main/java/sun/security/x509/AVA.java
index ff9c62a..a047500 100644
--- a/ojluni/src/main/java/sun/security/x509/AVA.java
+++ b/ojluni/src/main/java/sun/security/x509/AVA.java
@@ -150,9 +150,6 @@
/**
* Parse an AVA string formatted according to format.
- *
- * XXX format RFC1779 should only allow RFC1779 syntax but is
- * actually DEFAULT with RFC1779 keywords.
*/
AVA(Reader in, int format) throws IOException {
this(in, format, Collections.<String, String>emptyMap());
@@ -272,7 +269,7 @@
break;
}
- // Android-changed: Skip trailing whitespace.
+ // BEGIN Android-added: AVA: Support DerValue hex strings that contain ' ' or '\n'
if (c == ' ' || c == '\n') {
do {
if (c != ' ' && c != '\n') {
@@ -282,7 +279,7 @@
} while (!isTerminator(c, format));
break;
}
-
+ // END Android-added: AVA: Support DerValue hex strings that contain ' ' or '\n'
int cVal = hexDigits.indexOf(Character.toUpperCase((char)c));
if (cVal == -1) {
@@ -384,11 +381,17 @@
PRESERVE_OLD_DC_ENCODING == false)) {
// EmailAddress and DomainComponent must be IA5String
return new DerValue(DerValue.tag_IA5String,
+ // Android-changed: Do not trim() DerValue strings.
+ // temp.toString().trim());
temp.toString());
} else if (isPrintableString) {
+ // Android-changed: Do not trim() DerValue strings.
+ //return new DerValue(temp.toString().trim());
return new DerValue(temp.toString());
} else {
return new DerValue(DerValue.tag_UTF8String,
+ // Android-changed: Do not trim() DerValue strings.
+ // temp.toString().trim());
temp.toString());
}
}
@@ -900,6 +903,8 @@
* the dotted-decimal form.
*/
if ((typeAndValue.charAt(0) >= '0' && typeAndValue.charAt(0) <= '9') ||
+ // Android-changed: AVA: Support DerValue hex strings that contain ' ' or '\n'
+ //!isDerString(value, true))
(!isDerString(value, true) && value.tag != DerValue.tag_T61String))
{
byte[] data = null;
diff --git a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
index 378ca2f..260d4aa 100644
--- a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
+++ b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
@@ -121,18 +121,14 @@
try {
algParams = AlgorithmParameters.getInstance(algidString);
} catch (NoSuchAlgorithmException e) {
- // BEGIN Android-changed
- // It was searching for the EC parameters in an internal provider in the deleted package
- // sun.security.ec before setting them to null. Since EC is in the OpenSSL provider,
- // there's no need for such fallback. Setting it to null directly.
/*
* This algorithm parameter type is not supported, so we cannot
* parse the parameters.
*/
algParams = null;
return;
- // END Android-changed
}
+
// Decode (parse) the parameters
algParams.init(params.toByteArray());
}
@@ -246,11 +242,13 @@
}
}
+ // BEGIN Android-added: Update algorithm mapping tables for names when OID is used
// Try to update the name <-> OID mapping table.
synchronized (oidTable) {
reinitializeMappingTableLocked();
algName = nameTable.get(algid);
}
+ // END Android-added: Update algorithm mapping tables for names when OID is used
return (algName == null) ? algid.toString() : algName;
}
@@ -566,6 +564,7 @@
// See if any of the installed providers supply a mapping from
// the given algorithm name to an OID string
+ // BEGIN Android-changed: Update algorithm mapping tables for names when OID is used
synchronized (oidTable) {
reinitializeMappingTableLocked();
return oidTable.get(name.toUpperCase(Locale.ENGLISH));
@@ -644,17 +643,20 @@
initOidTableVersion = currentVersion;
}
+ // END Android-changed: Update algorithm mapping tables for names when OID is used
}
private static ObjectIdentifier oid(int ... values) {
return ObjectIdentifier.newInternal(values);
}
+ // BEGIN Android-changed: Parsing mapping as OID even if "OID." prefix isn't specified
private static int initOidTableVersion = -1;
private static final Map<String,ObjectIdentifier> oidTable =
new HashMap<String,ObjectIdentifier>(1);
private static final Map<ObjectIdentifier,String> nameTable =
new HashMap<ObjectIdentifier,String>();
+ // END Android-changed: Parsing mapping as OID even if "OID." prefix isn't specified
/*****************************************************************/
@@ -939,6 +941,8 @@
*/
sha1WithDSA_oid = ObjectIdentifier.newInternal(dsaWithSHA1_PKIX_data);
+ // Android-removed: Parsing mapping as OID even if "OID." prefix isn't specified
+ //nameTable = new HashMap<ObjectIdentifier,String>();
nameTable.put(MD5_oid, "MD5");
nameTable.put(MD2_oid, "MD2");
nameTable.put(SHA_oid, "SHA-1");
diff --git a/ojluni/src/main/java/sun/security/x509/CRLDistributionPointsExtension.java b/ojluni/src/main/java/sun/security/x509/CRLDistributionPointsExtension.java
index c381430..9062a53 100644
--- a/ojluni/src/main/java/sun/security/x509/CRLDistributionPointsExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/CRLDistributionPointsExtension.java
@@ -29,6 +29,7 @@
import java.io.OutputStream;
import java.util.*;
+import java.util.Collections;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
@@ -255,11 +256,12 @@
*/
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(POINTS)) {
- distributionPoints = new ArrayList<DistributionPoint>();
+ distributionPoints =
+ Collections.<DistributionPoint>emptyList();
} else {
throw new IOException("Attribute name [" + name +
- "] not recognized by " +
- "CertAttrSet:" + extensionName + ".");
+ "] not recognized by " +
+ "CertAttrSet:" + extensionName + '.');
}
encodeThis();
}
diff --git a/ojluni/src/main/java/sun/security/x509/CRLNumberExtension.java b/ojluni/src/main/java/sun/security/x509/CRLNumberExtension.java
index 9649df6..3abeb01 100644
--- a/ojluni/src/main/java/sun/security/x509/CRLNumberExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/CRLNumberExtension.java
@@ -157,11 +157,10 @@
*/
public BigInteger get(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
- if (crlNumber == null) return null;
- else return crlNumber;
+ return crlNumber;
} else {
- throw new IOException("Attribute name not recognized by"
- + " CertAttrSet:" + extensionName + ".");
+ throw new IOException("Attribute name not recognized by" +
+ " CertAttrSet:" + extensionName + '.');
}
}
diff --git a/ojluni/src/main/java/sun/security/x509/DNSName.java b/ojluni/src/main/java/sun/security/x509/DNSName.java
index 2a35b86..0946dd1b 100644
--- a/ojluni/src/main/java/sun/security/x509/DNSName.java
+++ b/ojluni/src/main/java/sun/security/x509/DNSName.java
@@ -232,15 +232,15 @@
* @throws UnsupportedOperationException if not supported for this name type
*/
public int subtreeDepth() throws UnsupportedOperationException {
- String subtree=name;
- int i=1;
+ // subtree depth is always at least 1
+ int sum = 1;
- /* count dots */
- for (; subtree.lastIndexOf('.') >= 0; i++) {
- subtree=subtree.substring(0,subtree.lastIndexOf('.'));
+ // count dots
+ for (int i = name.indexOf('.'); i >= 0; i = name.indexOf('.', i + 1)) {
+ ++sum;
}
- return i;
+ return sum;
}
}
diff --git a/ojluni/src/main/java/sun/security/x509/EDIPartyName.java b/ojluni/src/main/java/sun/security/x509/EDIPartyName.java
index feaf30b..513e337 100644
--- a/ojluni/src/main/java/sun/security/x509/EDIPartyName.java
+++ b/ojluni/src/main/java/sun/security/x509/EDIPartyName.java
@@ -197,7 +197,7 @@
*/
public int hashCode() {
if (myhash == -1) {
- myhash = 37 + party.hashCode();
+ myhash = 37 + (party == null ? 1 : party.hashCode());
if (assigner != null) {
myhash = 37 * myhash + assigner.hashCode();
}
diff --git a/ojluni/src/main/java/sun/security/x509/GeneralSubtrees.java b/ojluni/src/main/java/sun/security/x509/GeneralSubtrees.java
index 9c5e621..e5c9e73 100644
--- a/ojluni/src/main/java/sun/security/x509/GeneralSubtrees.java
+++ b/ojluni/src/main/java/sun/security/x509/GeneralSubtrees.java
@@ -191,7 +191,7 @@
// the list: if any subsequent entry matches or widens entry n,
// remove entry n. If any subsequent entries narrow entry n, remove
// the subsequent entries.
- for (int i = 0; i < size(); i++) {
+ for (int i = 0; i < (size() - 1); i++) {
GeneralNameInterface current = getGeneralNameInterface(i);
boolean remove1 = false;
diff --git a/ojluni/src/main/java/sun/security/x509/IPAddressName.java b/ojluni/src/main/java/sun/security/x509/IPAddressName.java
index 084a6f3..e558c9e 100644
--- a/ojluni/src/main/java/sun/security/x509/IPAddressName.java
+++ b/ojluni/src/main/java/sun/security/x509/IPAddressName.java
@@ -197,8 +197,10 @@
// append a mask corresponding to the num of prefix bits specified
int prefixLen = Integer.parseInt(name.substring(slashNdx+1));
- if (prefixLen > 128)
- throw new IOException("IPv6Address prefix is longer than 128");
+ if (prefixLen < 0 || prefixLen > 128) {
+ throw new IOException("IPv6Address prefix length (" +
+ prefixLen + ") in out of valid range [0,128]");
+ }
// create new bit array initialized to zeros
BitArray bitArray = new BitArray(MASKSIZE * 8);
@@ -317,7 +319,8 @@
if (!(obj instanceof IPAddressName))
return false;
- byte[] other = ((IPAddressName)obj).getBytes();
+ IPAddressName otherName = (IPAddressName)obj;
+ byte[] other = otherName.address;
if (other.length != address.length)
return false;
@@ -326,12 +329,10 @@
// Two subnet addresses
// Mask each and compare masked values
int maskLen = address.length/2;
- byte[] maskedThis = new byte[maskLen];
- byte[] maskedOther = new byte[maskLen];
for (int i=0; i < maskLen; i++) {
- maskedThis[i] = (byte)(address[i] & address[i+maskLen]);
- maskedOther[i] = (byte)(other[i] & other[i+maskLen]);
- if (maskedThis[i] != maskedOther[i]) {
+ byte maskedThis = (byte)(address[i] & address[i+maskLen]);
+ byte maskedOther = (byte)(other[i] & other[i+maskLen]);
+ if (maskedThis != maskedOther) {
return false;
}
}
@@ -400,7 +401,8 @@
else if (((IPAddressName)inputName).equals(this))
constraintType = NAME_MATCH;
else {
- byte[] otherAddress = ((IPAddressName)inputName).getBytes();
+ IPAddressName otherName = (IPAddressName)inputName;
+ byte[] otherAddress = otherName.address;
if (otherAddress.length == 4 && address.length == 4)
// Two host addresses
constraintType = NAME_SAME_TYPE;
diff --git a/ojluni/src/main/java/sun/security/x509/IssuingDistributionPointExtension.java b/ojluni/src/main/java/sun/security/x509/IssuingDistributionPointExtension.java
index 6a93258..6fe8eb3 100644
--- a/ojluni/src/main/java/sun/security/x509/IssuingDistributionPointExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/IssuingDistributionPointExtension.java
@@ -261,6 +261,7 @@
throw new IOException(
"Attribute value should be of type ReasonFlags.");
}
+ revocationReasons = (ReasonFlags)obj;
} else if (name.equalsIgnoreCase(INDIRECT_CRL)) {
if (!(obj instanceof Boolean)) {
@@ -290,7 +291,6 @@
}
hasOnlyAttributeCerts = ((Boolean)obj).booleanValue();
-
} else {
throw new IOException("Attribute name [" + name +
"] not recognized by " +
diff --git a/ojluni/src/main/java/sun/security/x509/KeyIdentifier.java b/ojluni/src/main/java/sun/security/x509/KeyIdentifier.java
index 01d4803..016fd4e 100644
--- a/ojluni/src/main/java/sun/security/x509/KeyIdentifier.java
+++ b/ojluni/src/main/java/sun/security/x509/KeyIdentifier.java
@@ -148,7 +148,7 @@
return true;
if (!(other instanceof KeyIdentifier))
return false;
- return java.util.Arrays.equals(octetString,
- ((KeyIdentifier)other).getIdentifier());
+ byte[] otherString = ((KeyIdentifier)other).octetString;
+ return java.util.Arrays.equals(octetString, otherString);
}
}
diff --git a/ojluni/src/main/java/sun/security/x509/OIDMap.java b/ojluni/src/main/java/sun/security/x509/OIDMap.java
index 9eed0f2..0e3ae16 100644
--- a/ojluni/src/main/java/sun/security/x509/OIDMap.java
+++ b/ojluni/src/main/java/sun/security/x509/OIDMap.java
@@ -112,6 +112,8 @@
/** Map String(friendly name) -> OIDInfo(info) */
private final static Map<String,OIDInfo> nameMap;
+ // BEGIN Android-changed: Specify Class objects rather for oidMap rather than String
+ // literals + reflection.
static {
oidMap = new HashMap<ObjectIdentifier,OIDInfo>();
nameMap = new HashMap<String,OIDInfo>();
@@ -200,6 +202,8 @@
return clazz;
}
}
+ // END Android-changed: Specify Class objects rather for oidMap rather than String
+ // literals + reflection.
/**
* Add a name to lookup table.
diff --git a/ojluni/src/main/java/sun/security/x509/PolicyMappingsExtension.java b/ojluni/src/main/java/sun/security/x509/PolicyMappingsExtension.java
index fba5104..e259826 100644
--- a/ojluni/src/main/java/sun/security/x509/PolicyMappingsExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/PolicyMappingsExtension.java
@@ -102,7 +102,7 @@
public PolicyMappingsExtension() {
extensionId = PKIXExtensions.KeyUsage_Id;
critical = false;
- maps = new ArrayList<CertificatePolicyMap>();
+ maps = Collections.<CertificatePolicyMap>emptyList();
}
/**
diff --git a/ojluni/src/main/java/sun/security/x509/PrivateKeyUsageExtension.java b/ojluni/src/main/java/sun/security/x509/PrivateKeyUsageExtension.java
index c20d855..512880b 100644
--- a/ojluni/src/main/java/sun/security/x509/PrivateKeyUsageExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/PrivateKeyUsageExtension.java
@@ -33,6 +33,7 @@
import java.security.cert.CertificateNotYetValidException;
import java.util.Date;
import java.util.Enumeration;
+import java.util.Objects;
import sun.security.util.*;
@@ -206,16 +207,17 @@
*/
public void valid(Date now)
throws CertificateNotYetValidException, CertificateExpiredException {
+ Objects.requireNonNull(now);
/*
* we use the internal Dates rather than the passed in Date
* because someone could override the Date methods after()
* and before() to do something entirely different.
*/
- if (notBefore.after(now)) {
+ if (notBefore != null && notBefore.after(now)) {
throw new CertificateNotYetValidException("NotBefore: " +
notBefore.toString());
}
- if (notAfter.before(now)) {
+ if (notAfter != null && notAfter.before(now)) {
throw new CertificateExpiredException("NotAfter: " +
notAfter.toString());
}
diff --git a/ojluni/src/main/java/sun/security/x509/RDN.java b/ojluni/src/main/java/sun/security/x509/RDN.java
index ed46abe..3bfc524 100644
--- a/ojluni/src/main/java/sun/security/x509/RDN.java
+++ b/ojluni/src/main/java/sun/security/x509/RDN.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -28,6 +28,8 @@
import java.io.IOException;
import java.io.StringReader;
+import java.util.Arrays;
+import java.util.StringJoiner;
import java.util.*;
import sun.security.util.*;
@@ -443,31 +445,19 @@
assertion[0].toRFC2253String(oidMap);
}
- StringBuilder relname = new StringBuilder();
- if (!canonical) {
- for (int i = 0; i < assertion.length; i++) {
- if (i > 0) {
- relname.append('+');
- }
- relname.append(assertion[i].toRFC2253String(oidMap));
- }
- } else {
+ AVA[] toOutput = assertion;
+ if (canonical) {
// order the string type AVA's alphabetically,
// followed by the oid type AVA's numerically
- List<AVA> avaList = new ArrayList<AVA>(assertion.length);
- for (int i = 0; i < assertion.length; i++) {
- avaList.add(assertion[i]);
- }
- java.util.Collections.sort(avaList, AVAComparator.getInstance());
-
- for (int i = 0; i < avaList.size(); i++) {
- if (i > 0) {
- relname.append('+');
- }
- relname.append(avaList.get(i).toRFC2253CanonicalString());
- }
+ toOutput = assertion.clone();
+ Arrays.sort(toOutput, AVAComparator.getInstance());
}
- return relname.toString();
+ StringJoiner sj = new StringJoiner("+");
+ for (AVA ava : toOutput) {
+ sj.add(canonical ? ava.toRFC2253CanonicalString()
+ : ava.toRFC2253String(oidMap));
+ }
+ return sj.toString();
}
}
@@ -488,11 +478,11 @@
* AVA's containing a standard keyword are ordered alphabetically,
* followed by AVA's containing an OID keyword, ordered numerically
*/
- @Override
public int compare(AVA a1, AVA a2) {
boolean a1Has2253 = a1.hasRFC2253Keyword();
boolean a2Has2253 = a2.hasRFC2253Keyword();
+ // BEGIN Android-changed: Keep sort order of RDN from Android M
if (a1Has2253) {
if (a2Has2253) {
return a1.toRFC2253CanonicalString().compareTo
@@ -516,6 +506,7 @@
a1Oid[pos] - a2Oid[pos];
}
}
+ // BEGIN Android-changed: Keep sort order of RDN from prev impl
}
}
diff --git a/ojluni/src/main/java/sun/security/x509/SubjectInfoAccessExtension.java b/ojluni/src/main/java/sun/security/x509/SubjectInfoAccessExtension.java
index 2f851f7..e1a0bc2 100644
--- a/ojluni/src/main/java/sun/security/x509/SubjectInfoAccessExtension.java
+++ b/ojluni/src/main/java/sun/security/x509/SubjectInfoAccessExtension.java
@@ -28,6 +28,7 @@
import java.io.IOException;
import java.io.OutputStream;
+import java.util.Collections;
import java.util.*;
import sun.security.util.DerOutputStream;
@@ -200,7 +201,8 @@
*/
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(DESCRIPTIONS)) {
- accessDescriptions = new ArrayList<AccessDescription>();
+ accessDescriptions =
+ Collections.<AccessDescription>emptyList();
} else {
throw new IOException("Attribute name [" + name +
"] not recognized by " +
diff --git a/ojluni/src/main/java/sun/security/x509/URIName.java b/ojluni/src/main/java/sun/security/x509/URIName.java
index 034117e..5f4021e 100644
--- a/ojluni/src/main/java/sun/security/x509/URIName.java
+++ b/ojluni/src/main/java/sun/security/x509/URIName.java
@@ -165,7 +165,7 @@
String host = uri.getSchemeSpecificPart();
try {
DNSName hostDNS;
- if (host.charAt(0) == '.') {
+ if (host.startsWith(".")) {
hostDNS = new DNSName(host.substring(1));
} else {
hostDNS = new DNSName(host);
diff --git a/ojluni/src/main/java/sun/security/x509/X500Name.java b/ojluni/src/main/java/sun/security/x509/X500Name.java
index 6090554..e708837 100644
--- a/ojluni/src/main/java/sun/security/x509/X500Name.java
+++ b/ojluni/src/main/java/sun/security/x509/X500Name.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -347,6 +347,8 @@
for (int i = 0; i < names.length; i++) {
list.addAll(names[i].avas());
}
+ list = Collections.unmodifiableList(list);
+ allAvaList = list;
}
return list;
}
@@ -365,9 +367,6 @@
*/
public boolean isEmpty() {
int n = names.length;
- if (n == 0) {
- return true;
- }
for (int i = 0; i < n; i++) {
if (names[i].assertion.length != 0) {
return false;
@@ -877,6 +876,7 @@
return;
}
+ // Android-added: refuse DN starting with new line or tab
checkNoNewLinesNorTabsAtBeginningOfDN(input);
List<RDN> dnVector = new ArrayList<>();
@@ -945,6 +945,7 @@
names = dnVector.toArray(new RDN[dnVector.size()]);
}
+ // BEGIN Android-added: refuse DN starting with new line or tab
/**
* Disallow new lines and tabs at the beginning of DN.
*
@@ -961,6 +962,7 @@
}
}
}
+ // END Android-added: refuse DN starting with new line or tab
private void parseRFC2253DN(String dnString) throws IOException {
if (dnString.length() == 0) {
@@ -1020,6 +1022,7 @@
static int countQuotes(String string, int from, int to) {
int count = 0;
+ // BEGIN Android-changed: Fix countQuotes in case of escaped backslashes: \\"
int escape = 0;
for (int i = from; i < to; i++) {
if (string.charAt(i) == '"' && escape % 2 == 0) {
@@ -1027,6 +1030,7 @@
}
escape = (string.charAt(i) == '\\') ? escape + 1 : 0;
}
+ // END Android-changed: Fix countQuotes in case of escaped backslashes: \\"
return count;
}
@@ -1130,12 +1134,8 @@
* and speed recognition of common X.500 attributes.
*/
static ObjectIdentifier intern(ObjectIdentifier oid) {
- ObjectIdentifier interned = internedOIDs.get(oid);
- if (interned != null) {
- return interned;
- }
- internedOIDs.put(oid, oid);
- return oid;
+ ObjectIdentifier interned = internedOIDs.putIfAbsent(oid, oid);
+ return (interned == null) ? oid : interned;
}
private static final Map<ObjectIdentifier,ObjectIdentifier> internedOIDs
diff --git a/ojluni/src/main/java/sun/security/x509/X509AttributeName.java b/ojluni/src/main/java/sun/security/x509/X509AttributeName.java
index 090792a..c60b6f4 100644
--- a/ojluni/src/main/java/sun/security/x509/X509AttributeName.java
+++ b/ojluni/src/main/java/sun/security/x509/X509AttributeName.java
@@ -47,7 +47,7 @@
*/
public X509AttributeName(String name) {
int i = name.indexOf(SEPARATOR);
- if (i == (-1)) {
+ if (i < 0) {
prefix = name;
} else {
prefix = name.substring(0, i);
diff --git a/ojluni/src/main/java/sun/security/x509/X509CRLImpl.java b/ojluni/src/main/java/sun/security/x509/X509CRLImpl.java
index 52e9818..e0021c8 100644
--- a/ojluni/src/main/java/sun/security/x509/X509CRLImpl.java
+++ b/ojluni/src/main/java/sun/security/x509/X509CRLImpl.java
@@ -748,9 +748,7 @@
public byte[] getTBSCertList() throws CRLException {
if (tbsCertList == null)
throw new CRLException("Uninitialized CRL");
- byte[] dup = new byte[tbsCertList.length];
- System.arraycopy(tbsCertList, 0, dup, 0, dup.length);
- return dup;
+ return tbsCertList.clone();
}
/**
@@ -761,9 +759,7 @@
public byte[] getSignature() {
if (signature == null)
return null;
- byte[] dup = new byte[signature.length];
- System.arraycopy(signature, 0, dup, 0, dup.length);
- return dup;
+ return signature.clone();
}
/**
diff --git a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
index de4d313..57a8f71 100644
--- a/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
+++ b/ojluni/src/main/java/sun/security/x509/X509CertImpl.java
@@ -192,7 +192,7 @@
}
}
- // BEGIN Android-removed
+ // BEGIN Android-removed: unused code
/*
/**
* unmarshals an X.509 certificate from an input stream. If the
@@ -266,7 +266,7 @@
der = new DerValue(decstream.toByteArray());
break;
} else {
- decstream.write(Base64.getMimeDecoder().decode(line));
+ decstream.write(Pem.decode(line));
}
}
} catch (IOException ioe2) {
@@ -280,7 +280,7 @@
return der;
}
*/
- // END Android-removed
+ // END Android-removed: unused code
/**
* Construct an initialized X509 Certificate. The certificate is stored
@@ -310,6 +310,7 @@
}
}
+ // BEGIN Android-added: Ctor to retain original encoded form for APKs parsing
/**
* Unmarshal a certificate from its encoded form, parsing a DER value.
* This form of constructor is used by agents which need to examine
@@ -327,6 +328,7 @@
throw new CertificateException("Unable to initialize, " + e, e);
}
}
+ // END Android-added: Ctor to retain original encoded form for APKs parsing
/**
* Appends the certificate to an output stream.
@@ -1023,9 +1025,7 @@
public byte[] getSignature() {
if (signature == null)
return null;
- byte[] dup = new byte[signature.length];
- System.arraycopy(signature, 0, dup, 0, dup.length);
- return dup;
+ return signature.clone();
}
/**
@@ -1784,6 +1784,7 @@
*/
private void parse(DerValue val)
throws CertificateException, IOException {
+ // BEGIN Android-added: Use original encoded form of cert rather than regenerating.
parse(
val,
null // use re-encoded form of val as the encoded form
@@ -1802,6 +1803,8 @@
*/
private void parse(DerValue val, byte[] originalEncodedForm)
throws CertificateException, IOException {
+ // END Android-added: Use original encoded form of cert rather than regenerating.
+
// check if can over write the certificate
if (readOnly)
throw new CertificateParsingException(
@@ -1811,6 +1814,8 @@
throw new CertificateParsingException(
"invalid DER-encoded certificate data");
+ // Android-changed: Needed for providing encoded form of cert
+ // signedCert = val.toByteArray();
signedCert =
(originalEncodedForm != null)
? originalEncodedForm : val.toByteArray();
diff --git a/ojluni/src/main/java/sun/security/x509/X509Key.java b/ojluni/src/main/java/sun/security/x509/X509Key.java
index 109cedf..789b7b8 100644
--- a/ojluni/src/main/java/sun/security/x509/X509Key.java
+++ b/ojluni/src/main/java/sun/security/x509/X509Key.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 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
@@ -31,7 +31,6 @@
import java.security.Key;
import java.security.PublicKey;
import java.security.KeyFactory;
-import java.security.KeyRep;
import java.security.Security;
import java.security.Provider;
import java.security.InvalidKeyException;
@@ -80,6 +79,7 @@
* Added to keep the byte[] key form consistent with the BitArray
* form. Can de deleted when byte[] key is deleted.
*/
+ @Deprecated
private int unusedBits = 0;
/* BitArray form of key */
@@ -245,7 +245,7 @@
throw new InstantiationException();
}
- Class keyClass = null;
+ Class<?> keyClass = null;
try {
keyClass = Class.forName(classname);
} catch (ClassNotFoundException e) {
diff --git a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
index 96e2e3d..ead18de 100644
--- a/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/AbstractCalendar.java
@@ -123,9 +123,15 @@
TimeZone zi = date.getZone();
if (zi != null) {
int[] offsets = new int[2];
- zoneOffset = zi.getOffset(millis);
- offsets[0] = zi.getRawOffset();
- offsets[1] = zoneOffset - offsets[0];
+ // BEGIN Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)zi).getOffsets(millis, offsets);
+ // } else {
+ zoneOffset = zi.getOffset(millis);
+ offsets[0] = zi.getRawOffset();
+ offsets[1] = zoneOffset - offsets[0];
+ // }
+ // END Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
// We need to calculate the given millis and time zone
// offset separately for java.util.GregorianCalendar
@@ -185,14 +191,25 @@
// 2) 5:00pm during DST is still interpreted as 5:00pm ST
// 3) 1:30am during ending-DST transition is interpreted
// as 1:30am ST (after transition)
- zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // ((ZoneInfo)zi).getOffsetsByStandard(ms, offsets);
+ // zoneOffset = offsets[0];
+ // } else {
+ zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // }
} else {
// 1) 2:30am during starting-DST transition is
// intrepreted as 3:30am DT
// 2) 5:00pm during DST is intrepreted as 5:00pm DT
// 3) 1:30am during ending-DST transition is interpreted
// as 1:30am DT/0:30am ST (before transition)
- zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // Android-changed: Android doesn't have sun.util.calendar.ZoneInfo.
+ // if (zi instanceof ZoneInfo) {
+ // zoneOffset = ((ZoneInfo)zi).getOffsetsByWall(ms, offsets);
+ // } else {
+ zoneOffset = zi.getOffset(ms - zi.getRawOffset());
+ // }
}
}
ms -= zoneOffset;
diff --git a/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java b/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
index 908bec8..a7e763a 100644
--- a/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/BaseCalendar.java
@@ -25,7 +25,6 @@
package sun.util.calendar;
-import java.util.Locale;
import java.util.TimeZone;
/**
diff --git a/ojluni/src/main/java/sun/util/calendar/CalendarDate.java b/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
index 205415e..b8e736c 100644
--- a/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
+++ b/ojluni/src/main/java/sun/util/calendar/CalendarDate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -435,7 +435,7 @@
return super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen
- throw new InternalError();
+ throw new InternalError(e);
}
}
diff --git a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
index 58707fb..3b9cbf7 100644
--- a/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
+++ b/ojluni/src/main/java/sun/util/calendar/CalendarSystem.java
@@ -75,25 +75,53 @@
/////////////////////// Calendar Factory Methods /////////////////////////
+ // BEGIN Android-changed: avoid reflection for loading calendar classes.
+ // // Map of calendar names and calendar class names
+ // private static ConcurrentMap<String, String> names;
// Map of calendar names and calendar classes;
private static final Map<String, Class<?>> names;
- // Android-changed: Don't use reflection for Class.forName every time.
+ // Map of calendar names and CalendarSystem instances
+ private static final ConcurrentMap<String, CalendarSystem> calendars =
+ new ConcurrentHashMap<>();
static {
names = new HashMap<>();
names.put("gregorian", Gregorian.class);
names.put("japanese", LocalGregorianCalendar.class);
names.put("julian", JulianCalendar.class);
- // names.put("hebrew", "HebrewCalendar");
- // names.put("iso8601", "ISOCalendar");
- // names.put("taiwanese", "LocalGregorianCalendar");
- // names.put("thaibuddhist", "LocalGregorianCalendar");
+ // END Android-changed: avoid reflection for loading calendar classes.
+ /*
+ "hebrew", "HebrewCalendar",
+ "iso8601", "ISOCalendar",
+ "taiwanese", "LocalGregorianCalendar",
+ "thaibuddhist", "LocalGregorianCalendar",
+ */
}
- // Map of calendar names and CalendarSystem instances
- private static final ConcurrentMap<String, CalendarSystem> calendars =
- new ConcurrentHashMap<>();
+ // BEGIN Android-removed: avoid reflection for loading calendar classes.
+ /*
+ private static void initNames() {
+ ConcurrentMap<String,String> nameMap = new ConcurrentHashMap<>();
+
+ // Associate a calendar name with its class name and the
+ // calendar class name with its date class name.
+ StringBuilder clName = new StringBuilder();
+ for (int i = 0; i < namePairs.length; i += 2) {
+ clName.setLength(0);
+ String cl = clName.append(PACKAGE_NAME).append(namePairs[i+1]).toString();
+ nameMap.put(namePairs[i], cl);
+ }
+ synchronized (CalendarSystem.class) {
+ if (!initialized) {
+ names = nameMap;
+ calendars = new ConcurrentHashMap<>();
+ initialized = true;
+ }
+ }
+ }
+ */
+ // END Android-removed: avoid reflection for loading calendar classes.
private final static Gregorian GREGORIAN_INSTANCE = new Gregorian();
@@ -122,7 +150,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) {
@@ -141,13 +169,12 @@
try {
cal = (CalendarSystem) calendarClass.newInstance();
} catch (Exception e) {
- throw new RuntimeException("internal error", e);
+ throw new InternalError(e);
}
}
if (cal == null) {
return null;
}
-
CalendarSystem cs = calendars.putIfAbsent(calendarName, cal);
return (cs == null) ? cal : cs;
}
@@ -161,7 +188,7 @@
* Unicode escape sequences
*/
public static Properties getCalendarProperties() throws IOException {
- // Android-changed: load from resources.
+ // Android-changed: load calendar Properties from resources.
Properties calendarProps = new Properties();
try (InputStream is = ClassLoader.getSystemResourceAsStream("calendars.properties")) {
calendarProps.load(is);
diff --git a/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java b/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
index 4d0922d..3c969a7 100644
--- a/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
+++ b/ojluni/src/main/java/sun/util/calendar/LocalGregorianCalendar.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -25,13 +25,7 @@
package sun.util.calendar;
-import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
@@ -60,6 +54,7 @@
private int gregorianYear = FIELD_UNDEFINED;
+ @Override
public Date setEra(Era era) {
if (getEra() != era) {
super.setEra(era);
@@ -68,12 +63,14 @@
return this;
}
+ @Override
public Date addYear(int localYear) {
super.addYear(localYear);
gregorianYear += localYear;
return this;
}
+ @Override
public Date setYear(int localYear) {
if (getYear() != localYear) {
super.setYear(localYear);
@@ -82,10 +79,12 @@
return this;
}
+ @Override
public int getNormalizedYear() {
return gregorianYear;
}
+ @Override
public void setNormalizedYear(int normalizedYear) {
this.gregorianYear = normalizedYear;
}
@@ -98,6 +97,7 @@
super.setYear(year);
}
+ @Override
public String toString() {
String time = super.toString();
time = time.substring(time.indexOf('T'));
@@ -118,20 +118,18 @@
}
static LocalGregorianCalendar getLocalGregorianCalendar(String name) {
- // Android-changed: use getCalendarProperties()
Properties calendarProps;
try {
- calendarProps = getCalendarProperties();
- } catch (IOException e) {
- throw new RuntimeException(e);
+ calendarProps = CalendarSystem.getCalendarProperties();
+ } catch (IOException | IllegalArgumentException e) {
+ throw new InternalError(e);
}
-
// Parse calendar.*.eras
String props = calendarProps.getProperty("calendar." + name + ".eras");
if (props == null) {
return null;
}
- List<Era> eras = new ArrayList<Era>();
+ List<Era> eras = new ArrayList<>();
StringTokenizer eraTokens = new StringTokenizer(props, ";");
while (eraTokens.hasMoreTokens()) {
String items = eraTokens.nextToken().trim();
@@ -168,11 +166,12 @@
Era era = new Era(eraName, abbr, since, localTime);
eras.add(era);
}
- // Android-changed: Throw if no eras were found, as other code depends on there being
- // at least one era.
+ // BEGIN Android-changed: Require at least one era.
+ // Other code depends on there being at least one era.
if (eras.isEmpty()) {
throw new RuntimeException("No eras for " + name);
}
+ // END Android-changed: Require at least one era.
Era[] eraArray = new Era[eras.size()];
eras.toArray(eraArray);
@@ -185,22 +184,27 @@
setEras(eras);
}
+ @Override
public String getName() {
return name;
}
+ @Override
public Date getCalendarDate() {
return getCalendarDate(System.currentTimeMillis(), newCalendarDate());
}
+ @Override
public Date getCalendarDate(long millis) {
return getCalendarDate(millis, newCalendarDate());
}
+ @Override
public Date getCalendarDate(long millis, TimeZone zone) {
return getCalendarDate(millis, newCalendarDate(zone));
}
+ @Override
public Date getCalendarDate(long millis, CalendarDate date) {
Date ldate = (Date) super.getCalendarDate(millis, date);
return adjustYear(ldate, millis, ldate.getZoneOffset());
@@ -229,14 +233,17 @@
return ldate;
}
+ @Override
public Date newCalendarDate() {
return new Date();
}
+ @Override
public Date newCalendarDate(TimeZone zone) {
return new Date(zone);
}
+ @Override
public boolean validate(CalendarDate date) {
Date ldate = (Date) date;
Era era = ldate.getEra();
@@ -270,6 +277,7 @@
return false;
}
+ @Override
public boolean normalize(CalendarDate date) {
if (date.isNormalized()) {
return true;
@@ -343,6 +351,7 @@
return true;
}
+ @Override
void normalizeMonth(CalendarDate date) {
normalizeYear(date);
super.normalizeMonth(date);
@@ -364,6 +373,7 @@
* Returns whether the specified Gregorian year is a leap year.
* @see #isLeapYear(Era, int)
*/
+ @Override
public boolean isLeapYear(int gregorianYear) {
return CalendarUtils.isGregorianLeapYear(gregorianYear);
}
@@ -376,6 +386,7 @@
return isLeapYear(gyear);
}
+ @Override
public void getCalendarDateFromFixedDate(CalendarDate date, long fixedDate) {
Date ldate = (Date) date;
super.getCalendarDateFromFixedDate(ldate, fixedDate);
diff --git a/ojluni/src/main/java/sun/util/locale/BaseLocale.java b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
index 6eee582..e0e9ed0 100644
--- a/ojluni/src/main/java/sun/util/locale/BaseLocale.java
+++ b/ojluni/src/main/java/sun/util/locale/BaseLocale.java
@@ -31,6 +31,7 @@
*/
package sun.util.locale;
+import java.lang.ref.SoftReference;
public final class BaseLocale {
@@ -163,11 +164,11 @@
return h;
}
- private static final class Key implements Comparable<Key> {
- private final String lang;
- private final String scrt;
- private final String regn;
- private final String vart;
+ private static final class Key {
+ private final SoftReference<String> lang;
+ private final SoftReference<String> scrt;
+ private final SoftReference<String> regn;
+ private final SoftReference<String> vart;
private final boolean normalized;
private final int hash;
@@ -179,10 +180,10 @@
assert language.intern() == language
&& region.intern() == region;
- lang = language;
- scrt = "";
- regn = region;
- vart = "";
+ lang = new SoftReference(language);
+ scrt = new SoftReference("");
+ regn = new SoftReference(region);
+ vart = new SoftReference("");
this.normalized = true;
int h = language.hashCode();
@@ -203,40 +204,40 @@
String variant, boolean normalized) {
int h = 0;
if (language != null) {
- lang = language;
+ lang = new SoftReference(language);
int len = language.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(language.charAt(i));
}
} else {
- lang = "";
+ lang = new SoftReference("");
}
if (script != null) {
- scrt = script;
+ scrt = new SoftReference(script);
int len = script.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(script.charAt(i));
}
} else {
- scrt = "";
+ scrt = new SoftReference("");
}
if (region != null) {
- regn = region;
+ regn = new SoftReference(region);
int len = region.length();
for (int i = 0; i < len; i++) {
h = 31*h + LocaleUtils.toLower(region.charAt(i));
}
} else {
- regn = "";
+ regn = new SoftReference("");
}
if (variant != null) {
- vart = variant;
+ vart = new SoftReference(variant);
int len = variant.length();
for (int i = 0; i < len; i++) {
h = 31*h + variant.charAt(i);
}
} else {
- vart = "";
+ vart = new SoftReference("");
}
hash = h;
this.normalized = normalized;
@@ -244,28 +245,31 @@
@Override
public boolean equals(Object obj) {
- return (this == obj) ||
- (obj instanceof Key)
- && this.hash == ((Key)obj).hash
- && LocaleUtils.caseIgnoreMatch(((Key)obj).lang, this.lang)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).scrt, this.scrt)
- && LocaleUtils.caseIgnoreMatch(((Key)obj).regn, this.regn)
- && ((Key)obj).vart.equals(vart); // variant is case sensitive in JDK!
+ if (this == obj) {
+ return true;
}
- @Override
- public int compareTo(Key other) {
- int res = LocaleUtils.caseIgnoreCompare(this.lang, other.lang);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.scrt, other.scrt);
- if (res == 0) {
- res = LocaleUtils.caseIgnoreCompare(this.regn, other.regn);
- if (res == 0) {
- res = this.vart.compareTo(other.vart);
+ if (obj instanceof Key && this.hash == ((Key)obj).hash) {
+ String tl = this.lang.get();
+ String ol = ((Key)obj).lang.get();
+ if (tl != null && ol != null &&
+ LocaleUtils.caseIgnoreMatch(ol, tl)) {
+ String ts = this.scrt.get();
+ String os = ((Key)obj).scrt.get();
+ if (ts != null && os != null &&
+ LocaleUtils.caseIgnoreMatch(os, ts)) {
+ String tr = this.regn.get();
+ String or = ((Key)obj).regn.get();
+ if (tr != null && or != null &&
+ LocaleUtils.caseIgnoreMatch(or, tr)) {
+ String tv = this.vart.get();
+ String ov = ((Key)obj).vart.get();
+ return (ov != null && ov.equals(tv));
}
}
}
- return res;
+ }
+ return false;
}
@Override
@@ -278,10 +282,10 @@
return key;
}
- String lang = LocaleUtils.toLowerString(key.lang).intern();
- String scrt = LocaleUtils.toTitleString(key.scrt).intern();
- String regn = LocaleUtils.toUpperString(key.regn).intern();
- String vart = key.vart.intern(); // preserve upper/lower cases
+ String lang = LocaleUtils.toLowerString(key.lang.get()).intern();
+ String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern();
+ String regn = LocaleUtils.toUpperString(key.regn.get()).intern();
+ String vart = key.vart.get().intern(); // preserve upper/lower cases
return new Key(lang, scrt, regn, vart, true);
}
@@ -294,12 +298,18 @@
@Override
protected Key normalizeKey(Key key) {
+ assert key.lang.get() != null &&
+ key.scrt.get() != null &&
+ key.regn.get() != null &&
+ key.vart.get() != null;
+
return Key.normalize(key);
}
@Override
protected BaseLocale createObject(Key key) {
- return new BaseLocale(key.lang, key.scrt, key.regn, key.vart);
+ return new BaseLocale(key.lang.get(), key.scrt.get(),
+ key.regn.get(), key.vart.get());
}
}
}
diff --git a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
index 378fb6c..81fa86e 100644
--- a/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
+++ b/ojluni/src/main/java/sun/util/locale/InternalLocaleBuilder.java
@@ -419,8 +419,9 @@
}
if (variant.length() > 0) {
- // normalize separators to "_"
+ // BEGIN Android-added: normalize separators to "_"
variant = variant.replaceAll(LanguageTag.SEP, BaseLocale.SEP);
+ // END Android-added: normalize separators to "_"
int errIdx = checkVariants(variant, BaseLocale.SEP);
if (errIdx != -1) {
throw new LocaleSyntaxException("Ill-formed variant: " + variant, errIdx);
diff --git a/ojluni/src/main/java/sun/util/locale/LanguageTag.java b/ojluni/src/main/java/sun/util/locale/LanguageTag.java
index fc7b07b..2247398 100644
--- a/ojluni/src/main/java/sun/util/locale/LanguageTag.java
+++ b/ojluni/src/main/java/sun/util/locale/LanguageTag.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -134,7 +134,7 @@
}
/*
- * BNF in RFC5464
+ * BNF in RFC5646
*
* Language-Tag = langtag ; normal language tags
* / privateuse ; private use tag
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
index 6b5f597..70fabc7 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleMatcher.java
@@ -212,7 +212,7 @@
if (range.equals("*")) {
continue;
}
-
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994
String rangeForRegex = range.replace("*", "\\p{Alnum}*");
while (rangeForRegex.length() > 0) {
for (String tag : tags) {
@@ -242,6 +242,7 @@
}
public static List<LanguageRange> parse(String ranges) {
+ // Android-changed: backport OpenJDK 9 fix for JDK-8166994
ranges = ranges.replace(" ", "").toLowerCase();
if (ranges.startsWith("accept-language:")) {
ranges = ranges.substring(16); // delete unnecessary prefix
@@ -331,6 +332,7 @@
return list;
}
+ // BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
/**
* A faster alternative approach to String.replaceFirst(), if the given
* string is a literal String, not a regex.
@@ -345,6 +347,7 @@
+ range.substring(pos + substr.length());
}
}
+ // END Android-added: backport OpenJDK 9 fix for JDK-8166994
private static String[] getEquivalentsForLanguage(String range) {
String r = range;
@@ -354,6 +357,9 @@
String equiv = LocaleEquivalentMaps.singleEquivMap.get(r);
// Return immediately for performance if the first matching
// subtag is found.
+// BEGIN Android-added: backport OpenJDK 9 fix for JDK-8166994
+// Upstream bug: https://bugs.openjdk.java.net/browse/JDK-8166994
+// Upstream fix: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/60837db5d445
return new String[]{replaceFirstSubStringMatch(range,
r, equiv)};
} else if (LocaleEquivalentMaps.multiEquivsMap.containsKey(r)) {
@@ -364,6 +370,7 @@
r, equivs[i]);
}
return result;
+// END Android-added: backport OpenJDK 9 fix for JDK-8166994
}
// Truncate the last subtag simply.
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
index 88920aa..eae1480 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleObjectCache.java
@@ -57,8 +57,10 @@
value = entry.get();
}
if (value == null) {
- key = normalizeKey(key);
V newVal = createObject(key);
+ // make sure key is normalized *after* the object creation
+ // so that newVal is assured to be created from a valid key.
+ key = normalizeKey(key);
if (key == null || newVal == null) {
// subclass must return non-null key/value object
return null;
diff --git a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
index 9a89dc0..ead48fc 100644
--- a/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
+++ b/ojluni/src/main/java/sun/util/locale/LocaleUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
diff --git a/ojluni/src/main/java/sun/util/logging/LoggingProxy.java b/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
index 9fbcc73..c044a5a 100644
--- a/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
+++ b/ojluni/src/main/java/sun/util/logging/LoggingProxy.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
diff --git a/ojluni/src/main/java/sun/util/logging/LoggingSupport.java b/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
index dd65b74..67b617d 100644
--- a/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
+++ b/ojluni/src/main/java/sun/util/logging/LoggingSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
diff --git a/ojluni/src/main/java/sun/util/logging/PlatformLogger.java b/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
index f9849c5..1ed8811 100644
--- a/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
+++ b/ojluni/src/main/java/sun/util/logging/PlatformLogger.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -84,22 +84,18 @@
* @since 1.7
*/
public class PlatformLogger {
- /*
- * These constants should be shortcuts to Level enum constants that
- * the clients of sun.util.logging.PlatformLogger require no source
- * modification and avoid the conversion from int to Level enum.
- *
- * This can be done when JavaFX is converted to use the new PlatformLogger.Level API.
- */
- public static final int OFF = Integer.MAX_VALUE;
- public static final int SEVERE = 1000;
- public static final int WARNING = 900;
- public static final int INFO = 800;
- public static final int CONFIG = 700;
- public static final int FINE = 500;
- public static final int FINER = 400;
- public static final int FINEST = 300;
- public static final int ALL = Integer.MIN_VALUE;
+
+ // The integer values must match that of {@code java.util.logging.Level}
+ // objects.
+ private static final int OFF = Integer.MAX_VALUE;
+ private static final int SEVERE = 1000;
+ private static final int WARNING = 900;
+ private static final int INFO = 800;
+ private static final int CONFIG = 700;
+ private static final int FINE = 500;
+ private static final int FINER = 400;
+ private static final int FINEST = 300;
+ private static final int ALL = Integer.MIN_VALUE;
/**
* PlatformLogger logging levels.
@@ -126,19 +122,19 @@
/* java.util.logging.Level */ Object javaLevel;
// ascending order for binary search matching the list of enum constants
- private static final int[] levelValues = new int[] {
+ private static final int[] LEVEL_VALUES = new int[] {
PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
};
public int intValue() {
- return levelValues[this.ordinal()];
+ return LEVEL_VALUES[this.ordinal()];
}
static Level valueOf(int level) {
switch (level) {
- // ordering per the highest occurences in the jdk source
+ // ordering per the highest occurrences in the jdk source
// finest, fine, finer, info first
case PlatformLogger.FINEST : return Level.FINEST;
case PlatformLogger.FINE : return Level.FINE;
@@ -152,7 +148,7 @@
}
// return the nearest Level value >= the given level,
// for level > SEVERE, return SEVERE and exclude OFF
- int i = Arrays.binarySearch(levelValues, 0, levelValues.length-2, level);
+ int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level);
return values()[i >= 0 ? i : (-i-1)];
}
}
@@ -169,23 +165,22 @@
}
});
- // Android-removed: Unnecessary on android, and gets in the way of obfuscated
- // releases.
- //
+ // Android-removed: JavaLoggerProxy is unneeded, complicates obfuscated releases.
+ /*
// force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
// less probable. Don't initialize JavaLoggerProxy class since
// java.util.logging may not be enabled.
- //
- // try {
- // Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
- // false,
- // PlatformLogger.class.getClassLoader());
- // Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
- // false, // do not invoke class initializer
- // PlatformLogger.class.getClassLoader());
- // } catch (ClassNotFoundException ex) {
- // throw new InternalError(ex.getMessage());
- // }
+ try {
+ Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
+ false,
+ PlatformLogger.class.getClassLoader());
+ Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
+ false, // do not invoke class initializer
+ PlatformLogger.class.getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ throw new InternalError(ex);
+ }
+ */
}
// Table of known loggers. Maps names to PlatformLoggers.
@@ -267,39 +262,6 @@
/**
* Returns true if a message of the given level would actually
* be logged by this logger.
- *
- * @deprecated Use isLoggable(Level) instead.
- */
- @Deprecated
- public boolean isLoggable(int levelValue) {
- return isLoggable(Level.valueOf(levelValue));
- }
-
- /**
- * Gets the current log level. Returns 0 if the current effective level is
- * not set (equivalent to Logger.getLevel() returns null).
- *
- * @deprecated Use level() instead
- */
- @Deprecated
- public int getLevel() {
- Level level = loggerProxy.getLevel();
- return level != null ? level.intValue() : 0;
- }
-
- /**
- * Sets the log level.
- *
- * @deprecated Use setLevel(Level) instead
- */
- @Deprecated
- public void setLevel(int newLevel) {
- loggerProxy.setLevel(newLevel == 0 ? null : Level.valueOf(newLevel));
- }
-
- /**
- * Returns true if a message of the given level would actually
- * be logged by this logger.
*/
public boolean isLoggable(Level level) {
if (level == null) {
@@ -588,6 +550,16 @@
String logClassName = "sun.util.logging.PlatformLogger";
boolean lookingForLogger = true;
+ // Android-changed: Different way to access throwable.getStackTrace()
+ // OpenJDK's faster way via SharedSecrets.getJavaLangAccess()
+ // is not available on Android.
+ /*
+ for (int ix = 0; ix < depth; ix++) {
+ // Calling getStackTraceElement directly prevents the VM
+ // from paying the cost of building the entire stack frame.
+ StackTraceElement frame =
+ access.getStackTraceElement(throwable, ix);
+ */
for (StackTraceElement frame : throwable.getStackTrace()) {
String cname = frame.getClassName();
if (lookingForLogger) {
diff --git a/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java b/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
index 86a91f8..462b0a7 100644
--- a/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
+++ b/ojluni/src/main/java/sun/util/resources/OpenListResourceBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -42,6 +42,7 @@
import java.util.Enumeration;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
@@ -66,7 +67,8 @@
}
// Implements java.util.ResourceBundle.handleGetObject; inherits javadoc specification.
- public Object handleGetObject(String key) {
+ @Override
+ protected Object handleGetObject(String key) {
if (key == null) {
throw new NullPointerException();
}
@@ -78,26 +80,39 @@
/**
* Implementation of ResourceBundle.getKeys.
*/
+ @Override
public Enumeration<String> getKeys() {
- ResourceBundle parent = this.parent;
- return new ResourceBundleEnumeration(handleGetKeys(),
- (parent != null) ? parent.getKeys() : null);
- }
+ ResourceBundle parentBundle = this.parent;
+ return new ResourceBundleEnumeration(handleKeySet(),
+ (parentBundle != null) ? parentBundle.getKeys() : null);
+ }
/**
- * Returns a set of keys provided in this resource bundle
+ * Returns a set of keys provided in this resource bundle,
+ * including no parents.
*/
- public Set<String> handleGetKeys() {
+ @Override
+ protected Set<String> handleKeySet() {
loadLookupTablesIfNecessary();
-
return lookup.keySet();
}
- /**
- * Returns the parent bundle
- */
- public OpenListResourceBundle getParent() {
- return (OpenListResourceBundle)parent;
+ @Override
+ public Set<String> keySet() {
+ if (keyset != null) {
+ return keyset;
+ }
+ Set<String> ks = createSet();
+ ks.addAll(handleKeySet());
+ if (parent != null) {
+ ks.addAll(parent.keySet());
+ }
+ synchronized (this) {
+ if (keyset == null) {
+ keyset = ks;
+ }
+ }
+ return keyset;
}
/**
@@ -118,12 +133,9 @@
* We lazily load the lookup hashtable. This function does the
* loading.
*/
- private synchronized void loadLookup() {
- if (lookup != null)
- return;
-
+ private void loadLookup() {
Object[][] contents = getContents();
- Map temp = createMap(contents.length);
+ Map<String, Object> temp = createMap(contents.length);
for (int i = 0; i < contents.length; ++i) {
// key must be non-null String, value must be non-null
String key = (String) contents[i][0];
@@ -133,16 +145,25 @@
}
temp.put(key, value);
}
- lookup = temp;
+ synchronized (this) {
+ if (lookup == null) {
+ lookup = temp;
+ }
+ }
}
/**
* Lets subclasses provide specialized Map implementations.
* Default uses HashMap.
*/
- protected Map createMap(int size) {
- return new HashMap(size);
+ protected <K, V> Map<K, V> createMap(int size) {
+ return new HashMap<>(size);
}
- private Map lookup = null;
+ protected <E> Set<E> createSet() {
+ return new HashSet<>();
+ }
+
+ private volatile Map<String, Object> lookup = null;
+ private volatile Set<String> keyset;
}
diff --git a/ojluni/src/main/native/NativeThread.c b/ojluni/src/main/native/NativeThread.c
index f8a68e7..9147bc3 100644
--- a/ojluni/src/main/native/NativeThread.c
+++ b/ojluni/src/main/native/NativeThread.c
@@ -35,8 +35,10 @@
#ifdef __linux__
#include <pthread.h>
#include <sys/signal.h>
+ // Android-changed: Bionic (and AsynchronousCloseMonitor) expects libcore to use
+ // __SIGRTMIN + 2, not __SIGRTMAX - 2
/* Also defined in net/linux_close.c */
- #define INTERRUPT_SIGNAL (__SIGRTMAX - 2)
+ #define INTERRUPT_SIGNAL (__SIGRTMIN + 2)
#elif __solaris__
#include <thread.h>
#include <signal.h>
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/linux_close.cpp b/ojluni/src/main/native/linux_close.cpp
index e9a2588..6f88c93 100644
--- a/ojluni/src/main/native/linux_close.cpp
+++ b/ojluni/src/main/native/linux_close.cpp
@@ -45,7 +45,9 @@
/*
* Signal to unblock thread
*/
-static int sigWakeup = (__SIGRTMAX - 2);
+// Android-changed: Bionic (and AsynchronousCloseMonitor) expects libcore to use
+// __SIGRTMIN + 2, not __SIGRTMAX - 2
+static int sigWakeup = (__SIGRTMIN + 2);
/*
* Close or dup2 a file descriptor ensuring that all threads blocked on
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/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/openjdk_java_files.mk b/openjdk_java_files.mk
index a812e07..81110ab 100644
--- a/openjdk_java_files.mk
+++ b/openjdk_java_files.mk
@@ -152,7 +152,6 @@
ojluni/src/main/java/java/lang/InternalError.java \
ojluni/src/main/java/java/lang/InterruptedException.java \
ojluni/src/main/java/java/lang/Iterable.java \
- ojluni/src/main/java/java/lang/JavaLangAccess.java \
ojluni/src/main/java/java/lang/LinkageError.java \
ojluni/src/main/java/java/lang/Long.java \
ojluni/src/main/java/java/lang/Math.java \
@@ -1342,6 +1341,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 := \
@@ -1378,7 +1397,6 @@
ojluni/src/main/java/sun/misc/FloatConsts.java \
ojluni/src/main/java/sun/misc/FormattedFloatingDecimal.java \
ojluni/src/main/java/sun/misc/FpUtils.java \
- ojluni/src/main/java/sun/misc/Hashing.java \
ojluni/src/main/java/sun/misc/HexDumpEncoder.java \
ojluni/src/main/java/sun/misc/InvalidJarIndexException.java \
ojluni/src/main/java/sun/misc/IOUtils.java \
@@ -1738,21 +1756,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/docs/crypto/README b/tools/docs/crypto/README
index cc6b6eb..9a34b7f 100644
--- a/tools/docs/crypto/README
+++ b/tools/docs/crypto/README
@@ -2,7 +2,8 @@
The central file is data/crypto_support.json, which is a JSON file that contains
the supported API levels for each crypto algorithm that has ever been supported
-by Android. The categories are identified as described in the JCA.
+by Android. The categories are identified as described in the JCA, along with
+a couple extra classes.
Each algorithm has up to three properties:
@@ -24,9 +25,8 @@
Getting the set of supported algorithms is done using
src/java/libcore/java/security/ListProviders.java. It's important that this is
-run using vogar (in mode=device, the default) rather than in an app container,
-as this documentation only includes the libcore-supported crypto support, but
-the Android frameworks (in particular, Android KeyStore) can add additional
+run using vogar in mode=activity rather than the default of mode=device, as
+the Android frameworks (in particular, Android Keystore) can add additional
support.
The data from ListProviders is fed into update_crypto_support.py, which rewrites
@@ -38,4 +38,5 @@
Finally, format_supported_algorithm_table.py reads the data file and outputs
a collection of HTML tables suitable for copying-and-pasting into the docs
-to stdout.
+to stdout. Add --javadoc to produce output appropriate for inclusion in
+Javadoc.
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)